POSTGRES——使用ON CONFLICT DO NOTHING防止序列递增

4

这个问题的重复

假设我有以下表格 "things"。我希望表格中的名称是唯一的,因此没有重复项。插入一个“thing”的过程不应该检查表中是否已经存在具有相同名称的“thing”。

CREATE TABLE things(
    id SMALLSERIAL PRIMARY KEY,
    name varchar UNIQUE
);

当我输入这样的值时,它会正常工作。如果“desk”已经存在于“things”中,它不会被插入。
INSERT INTO things (name)
VALUES ('desk')
ON CONFLICT DO NOTHING;

唯一的问题是ON CONFLICT DO NOTHING并不真正什么都不做,它仍会增加id字段的序列。

如果这种情况发生得太频繁,id序列最终可能会超出字段类型的限制。

有没有办法防止这种情况发生?


太频繁了?列数据类型? - jarlh
使用“bigint”并忘记这个问题。 - user330315
1个回答

8

使用insert ... on conflict,您无法防止serial在冲突时自动递增。Postgres(就像其他数据库一样)不保证序列化的连续性,如文档中所述

因为smallserialserialbigserial是使用序列实现的,即使没有删除任何行,该列中出现的值序列中可能会有“空洞”或间隔。从序列分配的值仍然被“用尽”,即使包含该值的行从未成功插入到表列中。例如,如果插入事务回滚,则可能会发生这种情况。

如果您运行了大量导致冲突的insert,限制损失的一种方法是将语法更改为not exists

insert into things (name)
select name
from (values ('desk')) v(name)
where not exists (select 1 from things t1 where t1.name = v.name)

请注意,这仍然不能保证串行号是连续的(请参阅文档中的上述引用)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接