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

Posted

技术标签:

【中文标题】Postgres ON CONFLICT 缺少我声明支持唯一索引的主键冲突【英文标题】:Postgres ON CONFLICT missing the primary key conflict I declared in favor of a unique index 【发布时间】:2020-11-11 23:19:59 【问题描述】:

我遇到了一个不常见但令人沮丧的问题,即 Postgres 似乎遗漏了我的主键冲突,并为唯一索引抛出了一个错误,我没有将其放入我的 ON CONFLICT 中。

一个例子是:

表:users

列:id (pkey), ext_id (unique index), attr1, attr2

INSERT INTO users("id", "ext_id", "attr1", "attr2")
VALUES (1, 123, 'a thing', 'something')
ON CONFLICT (id) DO UPDATE
SET "ext_id" = excluded.ext_id, "attr1" = excluded.attr1, "attr2" = excluded.attr2

有时它运行得很好,但有时它告诉我ERROR: duplicate key value violates unique constraint "index_users_on_ext_id"

我确定我缺少一些东西,但我不知道是什么。我是否需要从 SET 中删除唯一列?为什么这不总是抛出错误?

【问题讨论】:

显示表中的数据以及您尝试插入的数据,当这种“有时”发生时。只有一个地方可以触发唯一冲突,这就是ext_id 上的唯一索引。也许某些行已经有相同的ext_id ON CONFLICT (id) 更改为ON CONFLICT (id, ext_id) @AdrianKlaver 即使我没有 id 和 ext_id 的复合索引也可以使用? 【参考方案1】:

您收到此错误是因为 ext_id 确实已存在于数据库中。

没有简单的补救措施,因为您只能在ON CONFLICT 中指定单个约束。查看this question 以获得灵感。

如果您想跳过UPDATE 而不是收到错误,可以在UPDATE 子句中添加WHERE 条件。

【讨论】:

我也是这么理解的。但这是不可能的。因为这个db中已经存在匹配的记录,ID和ext_id相同。但错误仍然存​​在。没有包含 ext_id 但没有 ID 的记录。 这也会触发错误,但来自UPDATE 分支。查看我更改后的答案。

以上是关于Postgres ON CONFLICT 缺少我声明支持唯一索引的主键冲突的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Postgres INSERT ON CONFLICT DO UPDATE 与 INSERT 或 UPDATE

ON CONFLICT DO UPDATE 缺少 FROM 子句

在 clickhouse 上类似 ON CONFLICT DO NOTHING

Cassandra 中的 ON CONFLICT 运算符