この答えに関連して、説明できない現象に出くわしました。
バージョン:
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) 1 つのトランザクションでの複数の 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;