私は毎日スキーマを設計することはしませんが、設計するときは、管理を簡単にするためにカスケード更新/削除を正しくセットアップするようにしています。カスケードがどのように機能するかは理解していますが、どのテーブルがどれであるかを思い出すことはできません。
たとえば、2つのテーブルParent
とChild
がある場合、Child
を参照し、Parent
を参照し、ON DELETE CASCADE
、どのレコードがカスケードをトリガーし、どのレコードがカスケードによって削除されますか? Child
レコードはParent
レコードに依存しているため、Child
レコードが削除されるとParent
レコードが削除されますが、ON DELETE
があいまいです。これは、Parent
レコードが削除されたときにChild
レコードを削除することを意味するか、Child
が削除されたときにParent
レコードを削除することを意味します。どっち?
構文がON PARENT DELETE, CASCADE
、ON FOREIGN DELETE, CASCADE
またはあいまいさを取り除くために類似した何か。これを覚えるためのニーモニックは誰にもありますか?
Parent
とChild
の用語が好きで、覚えやすいと感じた場合は、_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!
_に変換できます。削除できるのは、子のない行だけです(削除されます)。
たとえば、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を指定しているが、デフォルト値が外部キー制約を満たさない場合、操作は失敗します。
ON DELETE
に適用できるON UPDATE
とFOREIGN 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');
すべてのbusiness
esがfatcat_owner
を介してbourgeoisie
の影響を直接受けている場合、労働者の革命後、fatcat_owner
sを削除してクラスのない社会を築くとどうなりますか?
-- Viva la revolución
BEGIN;
DELETE FROM bourgeoisie;
END;
ここにはいくつかのオプションがあります。
RESTRICT
。これはそれほど悪ではないと信じている人もいますが、通常は間違っています。続行させます。革命が起こった場合、SQLには4つのオプションがあります。
SET NULL
-空白のままにします。誰が知っている、多分資本主義が回復したのか、bourgeoisie
が登場し、寡頭政治家がfatcat_owners
の役割を果たします。重要な注意点として、列はNULLABLE
(NOT 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;
このようなシステムでは、トランザクションがコミットする前にのみ制約が検証されます。これにより革命が停止する可能性がありますが、トランザクションで回復できます-ある程度の「回復」。
簡単なニーモニックは
親CASCADEのON DELETE [ここで削除する]
これは、カスケードされる削除(親の削除)、ON DELETE CASCADEステートメントが(子で)実行される場所、および削除されるもの(子供)。