关于这个答案,我偶然发现了一个我无法解释的现象。
版本:
x86_64-unknown-linux-gnu 上的 PostgreSQL 9.1.2,由 gcc-4.4.real (Debian 4.4.5-8) 4.4.5 编译,64 位
试验台:
CREATE TEMP TABLE t (
id integer
, txt text
, CONSTRAINT t_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY IMMEDIATE
);
INSERT INTO t VALUES
(1, 'one')
, (2, 'two');
1)UPDATE
语句修改多行:
UPDATE t
SET id = t_old.id
FROM t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
上面的UPDATE
工作,虽然它预计它不应该。约束已定义INITIALLY IMMEDIATE
,我没有使用SET CONSTRAINTS
.
我错过了什么还是这是一个(相当无害的)错误?
2)数据修改CTE
因此,修改 CTE 的数据也有效。虽然它失败了一个NOT DEFERRED
pk:
WITH x AS (UPDATE t SET id = 1 WHERE id = 2)
UPDATE t SET id = 2 WHERE id = 1;
我引用了关于 CTE 的手册:
中的子语句
WITH
彼此同时执行并与主查询同时执行。因此,当在 中使用数据修改语句时WITH
,指定更新实际发生的顺序是不可预测的。所有语句都使用相同的快照执行(参见第 13 章),因此它们无法“看到”彼此对目标表的影响。
3) 一个事务中有多个 UPDATE 语句
如果没有SET CONSTRAINTS
,这将失败并出现 UNIQUE 违规 - 正如预期的那样:
BEGIN;
-- SET CONSTRAINTS t_pkey DEFERRED;
UPDATE t SET id = 2 WHERE txt = 'one';
UPDATE t SET id = 1 WHERE txt = 'two';
COMMIT;