POSTGRES - 使用 ON CONFLICT DO NOTHING 防止串行增量

Syn*_*ror 3 sql postgresql create-table auto-increment sql-insert

这个问题的副本

说我有下表的东西。我想要表中的唯一名称,所以没有重复。插入事物的过程不需要检查具有此名称的事物是否已经存在。

CREATE TABLE things(
    id SMALLSERIAL PRIMARY KEY,
    name varchar UNIQUE
);
Run Code Online (Sandbox Code Playgroud)

当我插入这样的值时,它会起作用。如果 'desk' 已经在东西里,它就不会被插入。

INSERT INTO things (name)
VALUES ('desk')
ON CONFLICT DO NOTHING;
Run Code Online (Sandbox Code Playgroud)

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

如果这种情况发生得太频繁,那么 id 序列最终会变得对于字段类型来说太大。

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

GMB*_*GMB 6

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

因为smallserial,serialbigserial是使用序列实现的,即使从未删除任何行,列中出现的值序列中也可能存在“漏洞”或间隙。即使包含该值的行从未成功插入到表列中,从该序列分配的值仍会“用完”。例如,如果插入事务回滚,则可能会发生这种情况。

如果您正在运行很多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)
Run Code Online (Sandbox Code Playgroud)

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