Postgres 什么时候检查唯一约束?

When does Postgres check unique constraints?

我有一个列 sort_order 具有唯一约束。 以下 SQL 在 Postgres 9.5 上失败:

UPDATE test
SET sort_order = sort_order + 1;

-- [23505] ERROR: duplicate key value violates unique constraint "test_sort_order_key"
--   Detail: Key (sort_order)=(2) already exists.

显然,如果 sort_order 值在更新前是唯一的,那么更新后它们仍然是唯一的。为什么是这样?

相同的语句在 Oracle 和 MS SQL 上工作正常,但在 MySQL 和 SQLite 上也失败。


这是 SQL fiddle 的完整设置代码:

DROP TABLE IF EXISTS test;
CREATE TABLE test (
  val        TEXT,
  sort_order INTEGER NOT NULL UNIQUE
);

INSERT INTO test
VALUES ('A', 1), ('B', 2);

Postgres 决定在不同于 SQL 标准建议的时间检查类型 IMMEDIATELY 的约束。

具体来说,SET CONSTRAINTS 的文档指出(强调我的):

NOT NULL and CHECK constraints are always checked immediately when a row is inserted or modified (not at the end of the statement). Uniqueness and exclusion constraints that have not been declared DEFERRABLE are also checked immediately.

Postgres 选择使用导致 sort_orderIMMEDIATELY 的临时冲突的计划执行此查询失败。请注意,这意味着 对于相同的架构和相同的数据,相同的查询可能会成功或失败,具体取决于执行计划。

您必须制定约束 DEFERRABLEDEFERRABLE INITIALLY DEFERRED,这会将约束的验证延迟到事务结束或语句 SET CONSTRAINTS ... IMMEDIATE被执行。

来自@HansGinzel 评论的附录:

for COPY, it seems, that (even IMMEDIATE) constraints are tested after all data are COPYied.