事実上、矛盾するルールで競合状態を作成します。
私の最初の衝動は、DEFERRED
制約が役立つかどうかを確認することでした。しかし、それは何の違いもないということは理にかなっています。
スクリプトで最初にCREATE TABLE
来る FK 制約がこの競争の勝者であることがわかりました。が最初に来る場合ON DELETE CASCADE
、削除はカスケードされ、ON DELETE RESTRICT
最初に来る場合、操作は中止されます。
SQL Fiddleのデモを検討してください。
oid
これは、カタログ テーブルの小さい方と相関しているようですpg_constraint
。
SELECT oid, * FROM pg_constraint WHERE conrelid = 'task'::regclass
しかし、あなたのフィードバックは、これが原因ではないことを示しています。たぶんpg_attribute.attnum
レースを決める。いずれにせよ、それが文書化された動作でない限り、次のメジャー バージョンでそのようにとどまることに依存することはできません。pgsql-general@postgresql.org に質問を投稿する価値があるかもしれません。
それとは独立して、他のCASCADE
行を考慮する必要があります。ケースを示す
別のSQL Fiddle 。task
tenant_id
customer_id
person
customer_id
person
制約を無効にする方法は?
あなたの最善の策は、それを落として再作成することです。参照整合性を損なわないように、トランザクション内ですべて実行してください。
BEGIN;
ALTER TABLE task DROP CONSTRAINT task_customer_id_fkey;
DELETE FROM person WHERE id = 3;
ALTER TABLE task ADD CONSTRAINT task_customer_id_fkey
FOREIGN KEY (customer_id) REFERENCES person (id) ON DELETE RESTRICT;
COMMIT;
これはテーブルを排他的にロックするため、マルチユーザー環境での日常的な使用には適していません。
制約の名前をどうやって知りましたか? pg_constraint
上記のように取得しました。最初は明示的な制約名を使用する方が簡単かもしれません:
CREATE TEMP TABLE task (
customer_id integer NOT NULL
,tenant_id integer NOT NULL REFERENCES person (id) ON DELETE CASCADE
,CONSTRAINT task_customer_id_fkey FOREIGN KEY (customer_id)
REFERENCES person (id) ON DELETE RESTRICT
);
もあります
ALTER TABLE task DISABLE trigger ALL;
詳細については、こちらのマニュアルを参照してください。しかし、それはすべてのトリガーを無効にします。単一の FK 制約を実装するためにシステムによって作成されたトリガーのみを無効にしようとしてもうまくいきませんでした。
他の選択肢は、トリガーまたはルールを使用して体制を実装することです。それは問題なく機能しますが、それらは外部キーほど厳密には適用されません。