web-dev-qa-db-ja.com

MySQLで外部キーにRESTRICTを使用する方法

のデータベース構造

  CREATE TABLE Country (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE City (
  name varchar(40) NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE Map (
  country varchar(40) NOT NULL,
  city varchar(100) NOT NULL,
  PRIMARY KEY  (country,city),
  FOREIGN KEY (country) REFERENCES Country (name) ON DELETE CASCADE,
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

これらの3つの同等のコマンドにより、子の対応する値をそのままにして、Cityから親を削除することを期待しています

  FOREIGN KEY (city) REFERENCES City (name) ON DELETE NO ACTION
  FOREIGN KEY (city) REFERENCES City (name) ON DELETE RESTRICT
  FOREIGN KEY (city) REFERENCES City (name)

ただし、NO ACTION OR RESTRICTを使用する場合、またはON DELETEを省略する場合。MySQLでは、次のエラーで親列から削除することはできません。

ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails 
('test'.'Map', CONSTRAINT 'Map_ibfk_2' FOREIGN KEY ('city') REFERENCES 'City'('name')
 ON DELETE RESTRICT

どこが間違っているのですか?親を削除して子を孤立させるのは、SQLのNO ACTIONの責任ではありませんか?

11
Googlebot

DELETE RESTRICTに関するMySQLドキュメント によると

•RESTRICT:親テーブルの削除または更新操作を拒否します。 RESTRICT(またはNO ACTION)を指定することは、ON DELETEまたはON UPDATE句を省略することと同じです。

ノーアクションも

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

DELETE RESTRICTは、子ではなく親を削除から保護します。

13
RolandoMySQLDBA

親を削除して子を残したい場合は、おそらく ON DELETE SET NULL オプション:

SET NULL:親テーブルから行を削除または更新し、子テーブルの1つまたは複数の外部キー列をNULLに設定します。 ON DELETE SET NULL句とON UPDATE SET NULL句の両方がサポートされています。

SET NULLアクションを指定する場合は、子テーブルの列をNOT NULLとして宣言していないことを確認してください。

最後の文には「not」がたくさんあるので、parent_idcanがNULLであることを確認してください。

この関連するqestionも参照してください: 外部キーの削除/更新制約でSET NULLの目的は何ですか?

外部キーを定義することで、親に対応する値を持たない子テーブルのエントリを受け入れないようにデータベースに指示しました。

5
Derek Downey