8

一連の遅延制約によって相互に依存している 2 つのテーブルから行を削除したいと考えています。この投稿を簡単にするために、単純な DB スキーマをモックアップしました。

SQL トランザクション/DB パッチ内のテーブル 'delete_from_me' からエントリを削除したいと考えています。キャッチは、リンク自体を失う前に、2番目のテーブル「constraining_table」からの選択に基づいて削除したいということです。

2 つのテーブルの説明は次のとおりです。

tab-quarantine=> \d delete_from_me
       Table "public.delete_from_me"
  Column   |       Type        | Modifiers 
-----------+-------------------+-----------
 id        | character varying | not null
 extension | character varying | not null
Indexes:
    "delete_from_me_pkey" PRIMARY KEY, btree (id)

tab-quarantine=> \d constraining_table 
   Table "public.constraining_table"
 Column |       Type        | Modifiers 
--------+-------------------+-----------
 image  | character varying | not null
 type   | character varying | not null
Foreign-key constraints:
    "constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id)
         ON UPDATE CASCADE
         ON DELETE RESTRICT DEFERRABLE

これは、私がそこに吹き込んだばかりのサンプルデータです。

tab-quarantine=> SELECT * FROM delete_from_me;
     id     | extension 
------------+-----------
 12345abcde | png
(1 row)

tab-quarantine=> SELECT * FROM constraining_table;
   image    |   type   
------------+----------
 12345abcde | select_me
(1 row)

そして、ここに私の取引があります:

BEGIN;
\set ON_ERROR_STOP 1
SET CONSTRAINTS ALL DEFERRED;
DELETE FROM delete_from_me WHERE id IN (
    SELECT image FROM constraining_table WHERE type = 'select_me'
);
DELETE FROM constraining_table WHERE type = 'select_me';
COMMIT;

このトランザクションは失敗します。ステップスルーしてこれを手動で行うと、次のエラーメッセージが表示されます。

ERROR:  update or delete on table "delete_from_me" violates foreign key constraint "constraining_table_image_fkey" on table "constraining_table"
DETAIL:  Key (id)=(12345abcde) is still referenced from table "constraining_table".

これは一時テーブルの良い候補のように思えますが、トランザクションの最後まで制約が有効にならないはずなのに、なぜこの順序で削除できないのか知りたいのですが?

4

1 に答える 1

12

ON DELETE NO ACTION DEFERRABLEの代わりに使用しON DELETE RESTRICT DEFERRABLEます。RESTRICT代わりに使用すると、修飾子NO ACTIONを適用するかどうかに関係なく、制約が強制的に延期できなくなります。DEFERRABLE

これは、のマニュアルページCREATE TABLEの細字部分にあります:

制約が延期可能と宣言されていても、NO ACTION チェック以外の参照アクションは延期できません。

明らかに、上記の警告にはRESTRICT.

この文の直後に、 と の定義が続きNO ACTIONますRESTRICT

何もしない

削除または更新によって外部キー制約違反が発生することを示すエラーを生成します。制約が延期されている場合、参照している行がまだ存在する場合、制約チェック時にこのエラーが生成されます。これがデフォルトのアクションです。

制限

削除または更新によって外部キー制約違反が発生することを示すエラーを生成します。これは、チェックが延期できないことを除いて、NO ACTION と同じです。

ご覧のとおり、 は遅延可能であることを除いNO ACTIONて、 と同じように動作します。これが私がそれをお勧めした理由です - 私はそれがまさにあなたが求めているものだと思います.RESTRICTNO ACTION

于 2010-07-19T16:48:17.237 に答える