没有与 ON CONFLICT 匹配的唯一或排除约束

新手上路,请多包涵

执行以下类型的插入时出现以下错误:

询问:

 INSERT INTO accounts (type, person_id) VALUES ('PersonAccount', 1) ON
CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET
updated_at = EXCLUDED.updated_at RETURNING *

错误:

SQL 执行失败(原因:错误:没有与 ON CONFLICT 规范匹配的唯一或排除约束)

我也有一个独特的索引:

 CREATE UNIQUE INDEX uniq_person_accounts ON accounts USING btree (type,
person_id) WHERE ((type)::text = 'PersonAccount'::text);

问题是有时它有效,但不是每次都有效。我 随机 得到了那个异常,这真的很奇怪。似乎它无法访问该 INDEX 或者它不知道它存在。

有什么建议吗?

我正在使用 PostgreSQL 9.5.5。

执行尝试查找或创建帐户的代码时的示例:

 INSERT INTO accounts (type, person_id, created_at, updated_at) VALUES ('PersonAccount', 69559, '2017-02-03 12:09:27.259', '2017-02-03 12:09:27.259') ON CONFLICT (type, person_id) WHERE type = 'PersonAccount' DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING *
 SQL execution failed (Reason: ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification)

在这种情况下,我确定该帐户不存在。此外,当这个人已经有一个帐户时,它永远不会输出错误。问题是,在某些情况下,如果还没有帐户,它也可以工作。查询完全相同。

原文由 Tiago Babo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
1 个回答

我通过为要包含在 ON CONFLICT 子句中的所有列创建一个 UNIQUE INDEX 解决了同样的问题,而不是为每一列创建一个 UNIQUE INDEX。

 CREATE TABLE table_name (
  element_id UUID NOT NULL DEFAULT gen_random_uuid(),
  timestamp TIMESTAMP NOT NULL DEFAULT now():::TIMESTAMP,
  col1 UUID NOT NULL,
  col2 STRING NOT NULL ,
  col3 STRING NOT NULL ,
  CONSTRAINT "primary" PRIMARY KEY (element_id ASC),
  UNIQUE (col1 asc, col2 asc, col3 asc)
);

这将允许查询

INSERT INTO table_name (timestamp, col1, col2, col3) VALUES ('timestamp', 'uuid', 'string', 'string')
ON CONFLICT (col1, col2, col3)
DO UPDATE timestamp = EXCLUDED.timestamp, col1 = EXCLUDED.col1, col2 = excluded.col2, col3 = col3.excluded;

原文由 Ruben1 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进