POSTGRES - 使用 ON CONFLICT DO NOTHING 防止串行增量 [重复]

Posted

技术标签:

【中文标题】POSTGRES - 使用 ON CONFLICT DO NOTHING 防止串行增量 [重复]【英文标题】:POSTGRES - prevent serial incrementation with ON CONFLICT DO NOTHING [duplicate] 【发布时间】:2020-12-22 11:55:42 【问题描述】:

duplicate of this question

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

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 序列最终会变得对于字段类型来说太大。

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

【问题讨论】:

太频繁了?列数据类型? 使用bigint 并忘记问题。 【参考方案1】:

使用insert ... on conflict,您无法阻止serial 自动增加冲突。 Postgres(就像其他数据库一样)不保证序列是连续的,如explained in the documentation:

因为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)

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

【讨论】:

以上是关于POSTGRES - 使用 ON CONFLICT DO NOTHING 防止串行增量 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Sequelize Postgres - 如何使用 ON CONFLICT 来实现独特的?

Postgres ON CONFLICT 缺少我声明支持唯一索引的主键冲突

Postgres INSERT ON CONFLICT DO UPDATE 与 INSERT 或 UPDATE

在 clickhouse 上类似 ON CONFLICT DO NOTHING

Cassandra 中的 ON CONFLICT 运算符

在 ON CONFLICT 子句中使用多个冲突目标