In connection with this answer I stumbled upon a phenomenon I cannot explain.
Version:
PostgreSQL 9.1.2 on x86_64-unknown-linux-gnu, compiled by gcc-4.4.real (Debian 4.4.5-8) 4.4.5, 64-bit
Testbed:
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
statement modifying multiple rows:
UPDATE t
SET id = t_old.id
FROM t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
The above UPDATE
works, though it expected it should not. The constraint is defined INITIALLY IMMEDIATE
and I did not use SET CONSTRAINTS
.
Am I missing something or is this a (rather harmless) bug?
2) Data modifying CTE
Consequently, a data modifying CTE works, too. Though it fails with a NOT DEFERRED
pk:
WITH x AS (UPDATE t SET id = 1 WHERE id = 2)
UPDATE t SET id = 2 WHERE id = 1;
I quote the manual on CTEs:
The sub-statements in WITH
are executed concurrently with each other
and with the main query. Therefore, when using data-modifying
statements in WITH
, the order in which the specified updates
actually happen is unpredictable. All the statements are executed with
the same snapshot (see Chapter 13), so they cannot "see" each
others' effects on the target tables.
3) Multiple UPDATE statements in one transaction
Without SET CONSTRAINTS
, this fails with a UNIQUE violation - as expected:
BEGIN;
-- SET CONSTRAINTS t_pkey DEFERRED;
UPDATE t SET id = 2 WHERE txt = 'one';
UPDATE t SET id = 1 WHERE txt = 'two';
COMMIT;
Question&Answers:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…