2016-08-19 92 views
0

得到一个表,我需要在删除重复项时填充数据。我正在使用ON CONFLICT ... DO NOTHING。问题是,当表中有一个auto_increment的primary_key字段时,-lets将其称为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万。这就是我想尽可能避免的。

回答

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; 
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。