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

POSTGRES - prevent serial incrementation with ON CONFLICT DO NOTHING

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

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

当我像这样插入值时它起作用了。如果 'desk' 已经在事物中,则不会插入。

INSERT INTO things (name)
VALUES ('desk')
ON CONFLICT DO NOTHING;

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

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

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

使用insert ... on conflict,你无法避免serial到auto-increment的冲突。 Postgres(就像其他数据库一样)不保证序列号是连续的,如 explained in the documentation:

Because smallserial, serial and bigserial are implemented using sequences, there may be "holes" or gaps in the sequence of values which appears in the column, even if no rows are ever deleted. A value allocated from the sequence is still "used up" even if a row containing that value is never successfully inserted into the table column. This may happen, for example, if the inserting transaction rolls back.

如果您 运行 很多 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)

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