Postgres什么时候检查独特的约束?

时间:2018-03-29 13:43:26

标签: postgresql unique-constraint

我有一个列sort_order,其上有一个唯一约束。 Postgres 9.5上的以下SQL失败:

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小提琴的完整设置代码:

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

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

1 个答案:

答案 0 :(得分:5)

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

具体来说,SET CONSTRAINTS州的文件(强调我的):

  

当插入或修改(不在语句末尾)行时,会立即检查NOT NULL和CHECK约束。还会立即检查尚未声明为DEFERRABLE的唯一性和排除约束。

Postgres选择使用导致sort_order暂时冲突且立即失败的计划执行此查询。请注意,对于相同的架构和相同的数据,表示相同的查询可能有效或失败,具体取决于执行计划。

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