At what point is a DEFERRED
/ DEFERRABLE
/ IMMEDIATE
unique / primary key constraint enforced exactly?
I am asking in connection with this answer.
Tried with this testbed in PostgreSQL 9.1.2:
CREATE TABLE tbl (
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 tbl t
SET id = t_old.id
FROM tbl t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
The above UPDATE
works, though I expected it to fail. The constraint is defined INITIALLY IMMEDIATE
and no SET CONSTRAINTS
was issued.
What am I missing?
2) Data modifying CTE
A data modifying CTE works the same. Though either fails with a NOT DEFERRED
PK:
WITH upd1 AS (
UPDATE tbl
SET id = 1
WHERE id = 2
)
UPDATE tbl
SET id = 2
WHERE id = 1;
The sub-statements in
WITH
are executed concurrently with each other and with the main query. Therefore, when using data-modifying statements inWITH
, 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 tbl SET id = 2 WHERE txt = 'one';
UPDATE tbl SET id = 1 WHERE txt = 'two';
COMMIT;