MySQLデータベースにparent
、child
の2つのテーブルがあります。親テーブルに基づいて、子テーブルに外部キー参照を追加しようとしています。 ON UPDATE CASCADE
とON DELETE CASCADE
の間に大きな違いはありますか
私の親テーブル
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
私の質問は、次のSQLクエリの違いは何ですか?.
ON DELETE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
ON UPDATE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE
) ENGINE=INNODB;
ON UPDATE CASCADE ON DELETE CASCADE
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=INNODB;
クエリにエラーはありますか?これらのクエリ(1、2、3)はどういう意味ですか?彼らは同じですか?
このテーマに関する非常に優れたスレッドが here および here にもあります。 MySQLの最も信頼できるガイドは、もちろんドキュメントです here 。
SQL 2003標準では、5つの異なる参照アクションがあります。
質問に答えるには:
[〜#〜]カスケード[〜#〜]
ON DELETE CASCADE
は、親レコードが削除されると、子レコードもすべて削除されることを意味します。これは私の考えでは良い考えではありません。これまでにデータベースに存在したすべてのデータを追跡する必要がありますが、これはTRIGGER
sを使用して行うことができます。 (ただし、以下のコメントの警告を参照してください)。
ON UPDATE CASCADE
は、親の主キーが変更されると、それを反映して子の値も変更されることを意味します。繰り返しになりますが、良い考えではありません。変更する場合PRIMARY KEY
sに規則性がある(またはまったく同じ)場合、デザインに問題があります。繰り返しますが、コメントを参照してください。
ON UPDATE CASCADE ON DELETE CASCADE
は、UPDATE
[〜#〜]または[〜#〜]DELETE
が親の場合、変更は子にカスケードされます。これは、最初の2つのステートメントの結果をAND
ingするのと同じです。
[〜#〜]制限[〜#〜]
RESTRICT
は、親を削除または更新しようとすると、エラーが発生して失敗することを意味します。これは、参照アクションが明示的に指定されていない場合のデフォルトの動作です。
ON DELETE
またはON UPDATE
指定されていない場合、デフォルトのアクションは常にRESTRICT`です。
アクションなし
NO ACTION
: manual から。標準SQLのキーワード。 MySQLでは、RESTRICT
と同等です。参照されるテーブルに関連する外部キー値がある場合、MySQLサーバーは親テーブルの削除または更新操作を拒否します。一部のデータベースシステムでは遅延チェックが行われ、NO ACTION
は遅延チェックです。 MySQLでは、外部キー制約はすぐにチェックされるため、NO ACTION
はRESTRICT
と同じです。SET NULL
SET NULL
-再びマニュアルから。親テーブルから行を削除または更新し、子テーブルの外部キー列をNULL
に設定します。これは、主に「時間移動」する方法がない、つまり、子テーブルを調べて、NULL
sのレコードを関連する親レコードに関連付けるCASCADE
またはTRIGGER
sを使用して、変更を追跡するためのロギングテーブルを生成します(ただし、コメントを参照)。SET DEFAULT
SET DEFAULT
。 MySQLが実装の手間をかけなかったSQL標準のもう1つの(潜在的に非常に役立つ)部分!開発者は、UPDATEまたはDELETEで外部キー列を設定する値を指定できます。 InnoDBとNDBは、SET DEFAULT
句。上記のように、ドキュメント here を確認するのに少し時間をかける必要があります。
これら2つは、親テーブルで参照されているレコードのIDが変更されたとき、および削除されたときにそれぞれ実行されるアクションです。
実行すると:
UPDATE parent SET id = -1 WHERE id = 1;
そして、child
にparent_id = 1
を含むレコードが少なくとも1つあります。1)は失敗します。 2)と3)の場合、parent_id = 1のすべてのレコードがparent_id = -1に更新されます。
実行すると:
DELETE FROM parent WHERE id = 1;
そして、child
に少なくとも1つのレコードがあり、parent_id = 1
が含まれています。2)は失敗します。 1)と3)の場合、parent_id = 1
を含むすべてのレコードが削除されます。
3)構文的に正しい。
完全なドキュメント マニュアルにあります 。
以前の回答についてコメントするのに十分な評判がありません。なので、もう少し詳しく説明したいと思いました。
1)ON DELETE CASCADEは、親レコードが削除されると、参照している子レコードもすべて削除されることを意味します。 ON UPDATEのデフォルトはRESTRICTです。これは、親レコードのUPDATEが失敗することを意味します。
2)ON DELETEアクションのデフォルトはRESTRICTです。つまり、親レコードのDELETEは失敗します。 ON UPDATE CASCADEは、親レコードが更新されると、参照しているすべての子レコードを更新します。
3)上記の1)および2)のCASCADEアクションを参照してください。
親レコードIDを外部キーとして(子テーブルで)使用する場合-経験によれば、a)IDが自動生成されたシーケンス番号の場合、外部キーとして使用しないでください。代わりに、他の一意の親キーを使用してください。 b)IDがGUIDの場合、それらを外部キーとして使用しても問題ありません。レコードをエクスポートしてインポートしたり、レコードを別のデータベースにコピーしたりするときに、この提案に知恵があります。データ移行中に自動生成されたシーケンス番号を外部キーとして参照する場合、それらを処理するのは面倒です。