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 子句