[MySQL] 外部キー制約を一時的に無効にする

MySQLで外部キー制約を適用しているテーブルにはDROP TABLEができません。

本番ではその挙動でもちろん良いのですが、開発中にテーブルをまるごと作り直したいときにはこの制約が邪魔になることがあります。またmysqldumpなどで出力したファイルをインポートする際にも、テーブルを順番通りインポートする必要が出てきます(外部キー制約があるとインポートに時間もかかりますよね)。

そういったときにforeign_key_checksの値に「0」をセットすることで一時的に外部キー制約を無効にすることができます。

SET foreign_key_checks = 0;

再び有効にするには「1」を代入します。

SET foreign_key_checks = 1;

本当に無効化できるか実験する

ここからは蛇足です。

実験用のテーブルを準備

ここでは都道府県(Ken)とユーザー情報(User)を管理するテーブルを用意することにします。

CREATE TABLE Ken(
  id int,
  name varchar(32),  -- "北海道", "青森県" ...

  PRIMARY KEY(id)
);

CREATE TABLE User (
  id   int,
  name varchar(64),  -- "ヨシヒコ"
  kenId int,         -- Ken.id

  PRIMARY KEY(id),
  FOREIGN KEY fkkenid(kenId) REFERENCES Ken(id)
);

外部キー制約のテスト(INSERT編)

Kenテーブルに存在しないidを、UserテーブルにINSERTしようとするとエラーになります。以下で言うと9番の都道府県は登録されていないのでエラーになっているのがわかります。安全。

mysql> INSERT INTO Ken VALUES(1, '北海道'), (2, '青森県'), (3, '岩手県');
Query OK, 3 rows affected (0.02 sec)

mysql> INSERT INTO User VALUES(1, 'ヨシヒコ', 1);
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO User VALUES(2, 'メレブ', 9);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`foo`.`User`, CONSTRAINT `User_ibfk_1` FOREIGN KEY (`kenId`) REFERENCES `Ken` (`id`))

外部キー制約のテスト(DROP TABLE編)

Userテーブルが参照しているKenテーブルは削除することはできません(Userの方はできます)

mysql> DROP TABLE Ken;
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails

外部キー制約を無効化

冒頭の変数に「0」を代入するだけで外部キー制約を無効にできることを試します。

mysql> SET foreign_key_checks = 0;
Query OK, 0 rows affected (0.00 sec)

では先ほどエラーになったINSERT文とDROP TABLE文を試していきます。あっけなく実現できしまって逆にびっくりするヤツですw

わざと不整合を起こす

何事もなかったように実行できてしまいます。不整合起こりまくりです。

mysql> INSERT INTO User VALUES(2, 'メレブ', 9);
Query OK, 1 row affected (0.01 sec)

わざとテーブルを削除する

参照先に指定されているテーブルもチェックされないためかんたんに削除できます。

mysql> DROP TABLE Ken;
Query OK, 0 rows affected (0.01 sec)

もとの設定状態に戻す

exitなどでクライアントを終了するか、foreign_key_checksに「1」を代入します。

mysql> SET foreign_key_checks = 1;

外部キー制約のチェックがOFFになっていた間にデータの不整合が発生していた場合、それらのデータはそのまま残り続けます。くれぐれもご注意ください。

現在の設定を確認する

SHOW VARIABLESで確認できます。デフォルトは「ON(1)」です。

mysql> SHOW VARIABLES LIKE 'foreign_key_checks';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| foreign_key_checks | OFF   |
+--------------------+-------+

参考ページ