当 运行 On Conflict 命令时控制 table 的主键值
Controlling a table's primary key value when running On Conflict command
得到一个 table,我需要在删除重复项的同时填充数据。我正在使用 ON CONFLICT ... DO NOTHING
。问题是,当 table 有一个 auto_increment primary_key 字段 - 让我们称之为 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 条记录,那么 max/last id 字段的值应为 4?
在我当前的案例中,我正在处理一个大型数据集,其中插入了 120 万条记录,但最后一条记录的 id 值为 6200 万。这就是我尽可能避免的事情。
您无法真正改变 ON CONFLICT 的行为。它所允许的只是更新冲突行而不是创建新行。
您可以重置序列并在之后重新分配 ID:
SELECT setval('table_one_id_seq', 1);
UPDATE table_one SET id = nextval('table_one_id_seq');
当然,您永远不应依赖最后一个 ID 来获取行数。如果您担心 ID 不足 运行,请使用 bigserial 而不是 serial。
您当然可以使用临时文件 table 来捕获和抑制重复项:
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;
得到一个 table,我需要在删除重复项的同时填充数据。我正在使用 ON CONFLICT ... DO NOTHING
。问题是,当 table 有一个 auto_increment primary_key 字段 - 让我们称之为 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 条记录,那么 max/last id 字段的值应为 4?
在我当前的案例中,我正在处理一个大型数据集,其中插入了 120 万条记录,但最后一条记录的 id 值为 6200 万。这就是我尽可能避免的事情。
您无法真正改变 ON CONFLICT 的行为。它所允许的只是更新冲突行而不是创建新行。
您可以重置序列并在之后重新分配 ID:
SELECT setval('table_one_id_seq', 1);
UPDATE table_one SET id = nextval('table_one_id_seq');
当然,您永远不应依赖最后一个 ID 来获取行数。如果您担心 ID 不足 运行,请使用 bigserial 而不是 serial。
您当然可以使用临时文件 table 来捕获和抑制重复项:
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;