web-dev-qa-db-ja.com

mysqlのOn Delete CascadeとOn Update Cascadeの違い

MySQLデータベースにparentchildの2つのテーブルがあります。親テーブルに基づいて、子テーブルに外部キー参照を追加しようとしています。 ON UPDATE CASCADEON 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)はどういう意味ですか?彼らは同じですか?

53
Lonewolf

このテーマに関する非常に優れたスレッドが here および here にもあります。 MySQLの最も信頼できるガイドは、もちろんドキュメントです here

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が親の場合、変更は子にカスケードされます。これは、最初の2つのステートメントの結果をANDingするのと同じです。

  2. [〜#〜]制限[〜#〜]

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

      ON DELETEまたはON UPDATE指定されていない場合、デフォルトのアクションは常にRESTRICT`です。

  3. アクションなし

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

    • SET NULL-再びマニュアルから。親テーブルから行を削除または更新し、子テーブルの外部キー列をNULLに設定します。これは、主に「時間移動」する方法がない、つまり、子テーブルを調べて、NULLsのレコードを関連する親レコードに関連付けるCASCADEまたはTRIGGERsを使用して、変更を追跡するためのロギングテーブルを生成します(ただし、コメントを参照)。
  5. SET DEFAULT

    • SET DEFAULT。 MySQLが実装の手間をかけなかったSQL標準のもう1つの(潜在的に非常に役立つ)部分!開発者は、UPDATEまたはDELETEで外部キー列を設定する値を指定できます。 InnoDBとNDBは、SET DEFAULT句。

上記のように、ドキュメント here を確認するのに少し時間をかける必要があります。

76
Vérace

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

実行すると:

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

そして、childparent_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)構文的に正しい。

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

9
jynus

以前の回答についてコメントするのに十分な評判がありません。なので、もう少し詳しく説明したいと思いました。

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の場合、それらを外部キーとして使用しても問題ありません。レコードをエクスポートしてインポートしたり、レコードを別のデータベースにコピーしたりするときに、この提案に知恵があります。データ移行中に自動生成されたシーケンス番号を外部キーとして参照する場合、それらを処理するのは面倒です。

6
g r