mysqlでのカスケードの削除とカスケードの更新の違い


45

MySQLデータベースに2つのテーブルがありますparent- child。親テーブルに基づいて、子テーブルに外部キー参照を追加しようとしています。間の有意差があるON UPDATE CASCADEとは、ON DELETE CASCADE

私の親テーブル

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

私の質問は次のとおりです。次のSQLクエリの違いは何ですか。

  1. 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;
  2. 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;
  3. 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)はどういう意味ですか?? 彼らは同じですか?


1
ps <nitpick>完全を期すために、上記で話しているのはDDL(データ定義言語)ステートメントであり、クエリではありません。クエリは、一般的にDML(データ操作言語SELECT、INSERT、UPDATE、DELETE)</ nitpick>であると考えられる
Vérace

完全を期すためにまた別のps、私はデフォルトが何だったのだろうか。そのため、更新時または削除時に子を作成しませんでした。その場合、依存する子を持つ親を更新したり削除したりすることはできません。完璧な理にかなっている、しかし、MySQLは常にその特定の特性のモデルではありません:-)
Vérace

回答:


64

このテーマに関する非常に良いスレッドは、ここここにもあります。MySQLの決定的なガイドは、もちろんここにあるドキュメントです

SQL 2003標準には、5つの異なる参照アクションがあります。

  1. カスケード
  2. 制限
  3. 何もしない
  4. NULLを設定
  5. デフォルト設定

質問に答えるには:

  1. カスケード

    • ON DELETE CASCADE親レコードが削除された場合、すべての子レコードも削除されることを意味します。これは私の意見では良い考えではありませんTRIGGERs を使用してこれを行うことはできますが、データベース内にあるすべてのデータを追跡する必要があります。(ただし、以下のコメントの警告を参照してください)。

    • ON UPDATE CASCADE親の主キーが変更された場合、子の値もそれを反映して変更されることを意味します。再び私の意見では、素晴らしいアイデアではありません。PRIMARY KEYsを規則的に(またはまったく)変更している場合、デザインに何か問題があります。繰り返しになりますが、コメントを参照してください。

    • ON UPDATE CASCADE ON DELETE CASCADEあなたの場合は、その手段UPDATE または DELETE親、変更が子供にカスケード接続されます。これは、AND最初の2つのステートメントの結果を取得することと同等です。

  2. 制限

    • RESTRICT親を削除または更新しようとすると、エラーのスローに失敗することを意味します。これは、参照アクションが明示的に指定されていない場合のデフォルトの動作です。

      以下のためON DELETEか、ON UPDATEそれが指定されていない、デフォルトのアクションは常にRESTRICT`です。

  3. 何もしない

    • NO ACTIONマニュアルから。標準SQLのキーワード。MySQLでは、と同等RESTRICTです。参照されるテーブルに関連する外部キー値がある場合、MySQLサーバーは親テーブルの削除または更新操作を拒否します。一部のデータベースシステムには遅延チェックNO ACTIONがあり、遅延チェックです。MySQLでは、外部キー制約はすぐにチェックされるためNO ACTION、と同じRESTRICTです。
  4. NULLを設定

    • SET NULL-再びマニュアルから。親テーブルから行を削除または更新し、子テーブルの外部キー列をに設定しNULLます。つまり子テーブルに背中を見てのレコードを関連付ける-これは「時間旅行」の方法がない主な理由、アイデアIMHOの最善ではありませんNULLどちらか-該当する親レコードとS CASCADEまたは使用TRIGGERトラックへのロギングテーブルを移入するための変更(ただし、コメントを参照)。
  5. デフォルト設定

    • SET DEFAULT。MySQLが実装を煩わせていないSQL標準のさらに別の(潜在的に非常に有用な)部分!開発者は、UPDATEまたはDELETEで外部キー列を設定する値を指定できます。InnoDBおよびNDBは、SET DEFAULT句を含むテーブル定義を拒否します。

上記のように、ここでドキュメントを見るのに時間をかける必要があります


8
私はあなたの完全な答えが好きですが、この声明には同意しません。「これまでデータベースにあったすべてのデータを追跡する必要があります」-これは、データベースの設計と目的に本当に依存しています。たとえば、レシピ定義(私は食べ物を話していません-システム構成に似ています)レシピ定義が削除されると、そのレシピの関連する子を保持することは意味がありません。また、マシンシステムの作業テーブル-データはもう必要ありません。処理し、それを取り除きます。それ以外は、あなたの答えは素晴らしいです。
StixO

2
@StixOに似ていますが、私はこの回答がほとんど好きですが、主キーの変更には反対しなければなりません。これが悪い考えとなる設計は確かにありますが、分散データベースにアクセスする場合、レコードのIDを失うことなくプライマリキーを自由に再割り当てできることが非常に望ましい場合があります。
ガレットクラボーン

「これは私の意見では良い考えではありません。データベースにあるすべてのデータを追跡する必要があります。」-私はあなたのポイントを理解しているかわかりません。「削除時に」カスケードしている場合は、何かを削除する必要があることをすでに決定しています。何も削除しないことに決めた場合、何もカスケードされません。ただし、それを使用する利点は、アプリケーションで外部IDを持つレコードを検索するときに、それが存在することを確認でき、削除することにした場合にデータベースを膨らませる孤立行がないことです。何か。
ジェフライアン

ここでの論理は、場所によってはかなり不完全であり、新しいGDPRの世界ではさらにそうです。主キーが変更されている場合、それは何か間違っている兆候かもしれないという考えに同意します。
チャックルバット

PRIMARY KEYを規則的に変更する場合(またはまったく変更する場合)、設計に何らかの問題があります。 ON UPDATE CASCADEがキーの値またはキーの名前を変更するということですか?
Billal Begueradj

8

これら2つは、親テーブルの参照レコードがそのIDを変更したとき、および削除されたときに、それぞれ実行されるアクションです。

実行する場合:

UPDATE parent SET id = -1 WHERE id = 1;

そして、上の少なくとも一つのレコードがあるchildparent_id = 1、1)は失敗しますが。ケース2)および3)では、parent_id = 1のすべてのレコードがparent_id = -1に更新されます。

実行する場合:

DELETE FROM parent WHERE id = 1;

また、childwithに少なくとも1つのレコードがありparent_id = 1、2)失敗します。ケース1)および3)では、すべてのレコードparent_id = 1が削除されます。

3)構文的に正しい。

完全なドキュメントはマニュアルにあります


6

以前の回答についてコメントするほどの評判はありません。それで、少し詳しく説明すると思いました。

1)ON DELETE CASCADEは、親レコードが削除された場合、参照している子レコードも削除されることを意味します。ON UPDATEのデフォルトはRESTRICTです。つまり、親レコードのUPDATEは失敗します。

2)ON DELETEアクションのデフォルトはRESTRICTです。これは、親レコードでのDELETEが失敗することを意味します。ON UPDATE CASCADEは、親レコードが更新されると、参照しているすべての子レコードを更新します。

3)上記1)および2)のCASCADEアクションを参照してください。

親レコードIDを(子テーブル内の)外部キーとして使用する場合-経験によると、IDが自動生成されたシーケンス番号である場合、それらを外部キーとして使用しないでください。代わりに他の一意の親キーを使用してください。b)IDがGUIDである場合、それらを外部キーとして使用してもかまいません。レコードをエクスポートおよびインポートするとき、またはレコードを別のデータベースにコピーするときに、この提案に知恵が表示されます。外部キーとして参照される場合、データ移行中に自動生成されたシーケンス番号を処理するのは面倒です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.