有一个表,我需要填充数据,同时摆脱重复。我正在使用ON CONFLICT ... DO NOTHING
。问题是,当表有一个auto_increment primary_key字段-lets称之为id
- 时,即使没有插入重复项时,该字段仍然会继续增加,因为id
字段值高于已成功插入的记录数。
不幸的是,SQL Fiddle目前不支持postgresql 9.5,所以我将复制粘贴下面的代码。
CREATE TABLE table_one
(
id serial primary key,
col_foo VARCHAR(40) not null unique,
col_bar VARCHAR(20)
);
INSERT into table_one (col_foo, col_bar)
VALUES ('1a', '1b'), ('2a', '2b'), ('1a', '2b'),('1a', Null), ('3a', '1b'), ('4a', '2b'), ('1a', '2b'),('1a', Null)
ON CONFLICT (col_foo) DO NOTHING;
如果你在postgresql 9.5上运行它,你会发现最终的主键是6,而只有4条记录。是否可以确保如果成功插入6个中的4个记录,则最大/最后一个id字段的值应为4?
在我目前的情况下,我正在处理一个大数据集,其中插入了120万条记录,但最后一条记录的id值为6200万。如果可能的话,这就是我想要避免的。
答案 0 :(得分:1)
您当然可以使用临时表来捕获和抑制重复项:
CREATE TABLE table_one
(
id serial primary key,
col_foo VARCHAR(40) not null unique,
col_bar VARCHAR(20)
);
CREATE TEMP TABLE temp_one
(
id serial primary key, -- dont actually need this
col_foo VARCHAR(40) not null unique,
col_bar VARCHAR(20)
);
INSERT into temp_one (col_foo, col_bar)
VALUES ('1a', '1b'), ('2a', '2b'), ('1a', '2b'),('1a', Null), ('3a', '1b'), ('4a', '2b'), ('1a', '2b'),('1a', Null)
ON CONFLICT (col_foo) DO NOTHING
;
INSERT into table_one (col_foo, col_bar)
SELECT col_foo, col_bar FROM temp_one
ON CONFLICT (col_foo) DO NOTHING -- wont need this
-- (except for suppressing already-existing duplicates)
;
SELECT * FROM temp_one;
SELECT * FROM table_one;
答案 1 :(得分:0)
你无法真正改变ON CONFLICT的行为。它允许的只是更新冲突行而不是创建新行。
您可以重置序列并在之后重新分配ID:
SELECT setval('table_one_id_seq', 1);
UPDATE table_one SET id = nextval('table_one_id_seq');
当然,你永远不应该依赖最后一个ID来获取行数。如果您担心ID耗尽,请使用bigserial而不是serial。