web-dev-qa-db-ja.com

カスケード(ON DELETE / UPDATE)動作の適切な説明

私は毎日スキーマを設計することはしませんが、設計するときは、管理を簡単にするためにカスケード更新/削除を正しくセットアップするようにしています。カスケードがどのように機能するかは理解していますが、どのテーブルがどれであるかを思い出すことはできません。

たとえば、2つのテーブルParentChildがある場合、Childを参照し、Parentを参照し、ON DELETE CASCADE、どのレコードがカスケードをトリガーし、どのレコードがカスケードによって削除されますか? ChildレコードはParentレコードに依存しているため、Childレコードが削除されるとParentレコードが削除されますが、ON DELETEがあいまいです。これは、Parentレコードが削除されたときにChildレコードを削除することを意味するか、Childが削除されたときにParentレコードを削除することを意味します。どっち?

構文がON PARENT DELETE, CASCADEON FOREIGN DELETE, CASCADEまたはあいまいさを取り除くために類似した何か。これを覚えるためのニーモニックは誰にもありますか?

111
Johntron

ParentChildの用語が好きで、覚えやすいと感じた場合は、_ON DELETE CASCADE_ to _Leave No Orphans!_

つまり、Parent行が削除(削除)された場合、Childテーブルで孤立行は存続しません。親行のすべての子も削除(削除)されます。これらの子のいずれかに孫が(別の外部キーを介して別のテーブルに)あり、_ON DELETE CASCADE_が定義されている場合、これらも削除する必要があります(カスケード効果が定義されている限り、すべての子孫も削除されます)。

_FOREIGN KEY_制約自体も_Allow No Orphans!_として記述できます(そもそも)。 Child(親テーブルの行)がない場合、子テーブルでParentを許可する(書き込む)ことはできません。

一貫性を保つために、_ON DELETE RESTRICT_は(あまり積極的ではない)_You Can't Kill Parents!_に変換できます。削除できるのは、子のない行だけです(削除されます)。

159
ypercubeᵀᴹ

たとえば、2つのテーブル(親と子)があり、子レコードが親レコードによって所有されている場合、どのテーブルにON DELETE CASCADEが必要ですか?

ON DELETE CASCADEは、外部キー宣言のオプションの句です。したがって、外部キーの宣言とwithになります。 (意味、「子」テーブル内。)

...これは、子レコードが削除されたときに親レコードを削除することを意味する場合と、親が削除されたときに子レコードを削除することを意味する場合があります。どっち?

外部キー宣言を解釈する1つの方法は、「この列のすべての有効な値は、「that_table」の「that_column」から取得されます。」 「子」テーブルの行を削除しても、誰も気にしません。データの整合性には影響しません。

「親」テーブル(「that_table」から)から行を削除すると、「子」テーブルの有効な値から有効な値が削除されます。データの整合性を維持するには、「子」テーブルに対してsomethingを実行する必要があります。削除のカスケードは、実行できる1つのことです。


PostgreSQL docs の章と節。

削除の制限とカスケードは、最も一般的な2つのオプションです。 RESTRICTは、参照された行の削除を防ぎます。 NO ACTIONは、制約のチェック時に参照行がまだ存在する場合、エラーが発生することを意味します。何も指定しない場合、これがデフォルトの動作です。 (これら2つの選択肢の本質的な違いは、NO ACTIONではチェックがトランザクションの後半まで据え置かれるのに対してRESTRICTでは行われないことです。)CASCADEは、参照される行が削除されると、それを参照する行が自動的に削除されることを指定します。同様に。他に2つのオプションがあります。SETNULLとSET DEFAULTです。これらにより、参照される行が削除されると、参照する行の参照列がそれぞれnullまたはそれらのデフォルト値に設定されます。これらは、制約を順守することを免除しないことに注意してください。たとえば、アクションがSET DEFAULTを指定しているが、デフォルト値が外部キー制約を満たさない場合、操作は失敗します。

SQL:2011仕様

ON DELETEに適用できるON UPDATEFOREIGN KEYには、5つのオプションがあります。これらは、SQL:2011仕様から直接、<referential actions>と呼ばれます。

  • ON DELETE CASCADE:参照されるテーブルの行が削除されると、参照するテーブルの一致するすべての行が削除されます。
  • ON DELETE SET NULL:参照されるテーブルの行が削除されると、参照するテーブルの一致するすべての行のすべての参照列がnullに設定されます。
  • ON DELETE SET DEFAULT:参照されるテーブルの行が削除された場合、参照テーブルのすべての一致する行のすべての参照列が列のデフォルト値に設定されます。
  • ON DELETE RESTRICT:参照先のテーブルの行に一致する行がある場合、その行を削除することは禁止されています。
  • ON DELETE NO ACTION(デフォルト):参照削除アクションはありません。参照制約は制約チェックのみを指定します。

外部キーは依存関係を確立します。 <referential action>は、関係が解消されたときに何が起こるかを決定します。

例/メタファー/説明

この例では、社会と経済の一般的なモデルを受け入れます。ここで、すべてのbusinessは、fatcat_ownerを通じてbourgeoisieとの関係を維持する会社です。

CREATE TABLE bourgeoisie(
  fatcat_owner varchar(100) PRIMARY KEY
);
INSERT INTO bourgeoisie(fatcat_owner) VALUES
  ( 'Koch Brothers' );

CREATE TABLE business (
  name         varchar(100),
  fatcat_owner varchar(100) REFERENCES bourgeoisie
);
INSERT INTO business(name, fatcat_owner)
  VALUES ('Georgia-Pacific', 'Koch Brothers');

すべてのbusinessesがfatcat_ownerを介してbourgeoisieの影響を直接受けている場合、労働者の革命後、fatcat_ownersを削除してクラスのない社会を築くとどうなりますか?

-- Viva la revolución 
BEGIN;
  DELETE FROM bourgeoisie;
END;

ここにはいくつかのオプションがあります。

  • 革命を止めなさい。 SQL用語では、RESTRICT。これはそれほど悪ではないと信じている人もいますが、通常は間違っています。
  • 続行させます。革命が起こった場合、SQLには4つのオプションがあります。

    • SET NULL-空白のままにします。誰が知っている、多分資本主義が回復したのか、bourgeoisieが登場し、寡頭政治家がfatcat_ownersの役割を果たします。重要な注意点として、列はNULLABLENOT NULLではない)である必要があります。そうしないと、これが発生することはありません。
    • SET DEFAULT-これを処理するDEFAULTをお持ちでしたか? DEFAULTは関数を呼び出すことができます。おそらく、あなたのスキーマはすでに革命の準備が整っています。
    • CASCADE-ダメージコントロールはありません。 bourgeoisieが使用される場合、businessも使用されます。ビジネスが必須fatcat_pigが必要な場合、場合によっては、businessにビジネス以外のデータを含めるよりも、データを失うほうが理にかなっています。テーブル。
    • NO ACTION-これは本質的にチェックを遅延させる方法です。MySQLではRESTRICTと同じですが、PostgreSQLでは次のことができます

      -- Not a real revolution.
      -- requires constraint be DEFERRABLE INITIALLY DEFERRED
      BEGIN;
        SET CONSTRAINTS ALL DEFERRED;
        DELETE FROM bourgeoisie;
        INSERT INTO bourgeoisie VALUES ( 'Putin' );
        UPDATE business SET fatcat_pig = 'Putin';
      END;
      

      このようなシステムでは、トランザクションがコミットする前にのみ制約が検証されます。これにより革命が停止する可能性がありますが、トランザクションで回復できます-ある程度の「回復」。

4
Evan Carroll

簡単なニーモニックは

親CASCADEのON DELETE [ここで削除する]

これは、カスケードされる削除(親の削除)、ON DELETE CASCADEステートメントが(子で)実行される場所、および削除されるもの(子供)。

2
msouth