InnoDB
は
外部キー制約もまたサポートします。InnoDB
内の外部キー制約定義の構文は次のようになります:
[CONSTRAINTsymbol
] FOREIGN KEY [id
] (index_col_name
, ...) REFERENCEStbl_name
(index_col_name
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
外部キー定義には次のような条件があります:
両方のテーブルは InnoDB
テーブルである必要があり、それらは
TEMPORARY
テーブルではいけません。
参照表の中では、外部キーカラムが同じ順番で first カラムとしてリストされているインデックスが存在する必要があります。もしそのようなインデックスが無ければ、自動的に参照表上に作成されます。
参照表の中では、参照カラムが同じ順番で first カラムとしてリストされているインデックスが存在する必要があります。
外部キー カラム上のインデックス
プリフィックスはサポートされていません。この1つの結論は、それらのカラム上のインデックスは常にプリフィックス長を含む必要がある為、BLOB
と TEXT
カラムを外部キー内に含む事ができないという事です。
もし CONSTRAINT
条項が与えられると、symbol
symbol
値はデータベース上で固有である必要があります。もし条項が与えられなければ、InnoDB
は名前を自動的に作成します。
もし親テーブル内に適合する候補キー値が無ければ、InnoDB
は子テーブル内に外部キー値を作成しようとする
INSERT
か UPDATE
操作を拒絶します。子テーブル内にいくつかの適合する行を持つ親テーブル内で、候補キー値を更新または削除しようとする
UPDATE
や DELETE
操作に対して InnoDB
が取るアクションは、FOREIGN KEY
条項の ON UPDATE
と ON
DELETE
サブ条項を利用して指定された
referential action
上で依存しています。ユーザが親テーブルから行を削除または更新しようとして、子テーブル内に1つ以上の適合する行がある時、InnoDB
は取るべきアクションを考慮して5つのオプションをサポートします:
CASCADE
:親テーブルから行を削除または更新し、子テーブル内で自動的に適合行を削除または更新します。ON
DELETE CASCADE
と ON UPDATE
CASCADE
の両方がサポートされています。2つのテーブルの間で、親テーブル内、または子テーブル内で同じカラム上に機能するいくつかの
ON UPDATE CASCADE
条項を定義するべきでは有りません。
SET
NULL
:親テーブルから行を削除または更新し、子テーブル内で外部キー
カラムを NULL
に設定します。これは外部キー
カラムが指定された NOT NULL
修飾子を持たない時だけ有効です。 ON
DELETE SET NULL
と ON UPDATE SET
NULL
条項の両方がサポートされています。
NO ACTION
:スタンダード SQL
内で、NO ACTION
は、もし参照表内に関連する外部キーがあれば主キー値を削除または更新しようとする事は許容されていないという意味で、
no action
を意味します。InnoDB
は親テーブルの削除または更新操作を拒否します。
RESTRICT
:親テーブルの削除または更新操作を拒否します。NO
ACTION
と RESTRICT
は
ON DELETE
か ON
UPDATE
条項を省略する事と同じです。(いくつかのデータベース
システムが据え置きチェックを持ち、NO
ACTION
が据え置きチェックです。MySQL
内では、外部キー制約は即座に確認されるので、NO
ACTION
と RESTRICT
は同じです。)
SET
DEFAULT
:このアクションはパーサによって認識されますが、InnoDB
は ON DELETE SET DEFAULT
か ON
UPDATE SET DEFAULT
条項を含むテーブル定義を拒否します。
InnoDB
がテーブル内で外部キー制約をサポートする事に注意してください。これらのような場合、「子テーブル
レコード」
は本当に同じテーブル内で依存レコードを参照します。
InnoDB
は、外部キー
チェックが速くなり、テーブル
スキャンを必要としないよう、外部キーと参照キー上にインデックスを要求します。外部キー上のインデックスは自動的に作成されます。これは、いくつかの古いバージョン内での、インデックスが明示的に作成される必要があり、そうでなければ外部キー制約の作成が失敗する、という物とは対照的です。
タイプ変換をせずに比較できるよう、外部キーと参照キー内の対応するカラムは
InnoDB
内に類似内部データ
タイプを持つ必要があります。整数タイプのサイズとサインは同じである必要があります。文字列タイプの長さは同じである必要はありません。もし
SET NULL
アクションを指定したら、
子テーブル内のカラムを NOT
NULL
として宣言していない事を確認してください。
もし MySQL が CREATE
TABLE
ステートメントからエラー番号1005を報告し、そのエラーメッセージがエラー150を参照していたら、外部キー制約が正しく形作られていない為にテーブル作成は失敗します。
同じように、もし ALTER TABLE
が失敗し、それがエラー150を参照していたら、それは変更したテーブルに対して外部キー制約が間違って形作られるという意味になります。
サーバ内に一番新しい InnoDB
外部キー エラーの詳細説明を表示する為に
SHOW ENGINE INNODB STATUS
を利用する事ができます。
注意:InnoDB
は NULL
カラムを含む外部キーや参照キー上で外部キー制約を確認しません。
注意:トリガは現在、転送された外部キー アクションによって有効化されません。
内部 InnoDB
カラムの名前と一致するカラム名を持つテーブルを作成する事はできません。(DB_ROW_ID
、DB_TRX_ID
、DB_ROLL_PTR
そして DB_MIX_ID
を含む)MySQL
5.1.10以前のバージョン内ではこれはクラッシュの原因となり、5.1.10からはサーバがエラー1005を報告し、エラーメッセージ内で
errno
-1 を参照します。
SQL
スタンダードからの逸脱:InnoDB
は同じ参照キー値を持つ親テーブル内にいくつかの行があると、外部キーチェック内で同じキー値を持つ別の親行がまるで存在しないかのように機能します。例えば、もし
RESTRICT
タイプ制約を定義し、いくつかの親行を持つ子行があれば、InnoDB
はそれらの親行の削除を許可しません。
InnoDB
は、外部キー制約に対応するインデックス内のレコードに基づいた、縦型アルゴリズムを通して転送操作を行います。
SQL
スタンダードからの逸脱:非
UNIQUE
キーを参照する FOREIGN
KEY
制約はスタンダード SQL
ではありません。それはスタンダード SQL への
InnoDB
拡張子です。
SQL
スタンダードからの逸脱:もし ON
UPDATE CASCADE
か ON UPDATE SET
NULL
が転送の最中に既に更新された
同じテーブル
の更新を反復すると、それは
RESTRICT
のように機能します。これは、自己参照型
ON UPDATE CASCADE
か ON UPDATE SET
NULL
操作を利用する事ができないという意味です。これは転送更新の結果に起きる無限ループを防ぐ為の物です。反対に、自己参照型
ON DELETE SET NULL
は、自己参照型
ON DELETE CASCADE
と同様可能です。転送操作は15レベルより深くネスト化される事はないでしょう。
SQL
スタンダードからの逸脱:通常の MySQL
のように、挿入、削除、または多くの行の更新を行う
SQL ステートメント内では、InnoDB
は UNIQUE
と FOREIGN KEY
制約を行ごとに行います。SQL
スタンダードによると、デフォルト動作は据え置きチェックでなければいけません。それは、SQL
ステートメント全体
が処理された後に制約の確認だけが行われるいう事です。InnoDB
が据え置き制約チェックを実装するまでは、外部キーを通してそれ自身を参照するレコードを削除するというような、いくつかの操作を行う事が不可能になります。
ここに、単一カラム外部キーを通して
parent
と child
テーブルを関連させるシンプルな例があります:
CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id) ) ENGINE=INNODB; 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;
product_order
テーブルが別の2つのテーブルに外部キーを持つ、さらに複雑な例。1つの外部キーが
product
テーブル内の2段インデックスに参照をつけます。その他の物は
customer
テーブル内で単一カラム
インデックスに参照をつけます:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB; CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(no), INDEX (product_category, product_id), FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), FOREIGN KEY (customer_id) REFERENCES customer(id)) ENGINE=INNODB;
InnoDB
は ALTER TABLE
を利用してテーブルに新しい外部キー制約を追加する事を許容します:
ALTER TABLEtbl_name
ADD [CONSTRAINTsymbol
] FOREIGN KEY [id
] (index_col_name
, ...) REFERENCEStbl_name
(index_col_name
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
要求されたインデックスを最初に作成する事を忘れないでください。.ALTER
TABLE
を利用して、自己参照型外部キー制約をテーブルに追加する事もできます。
InnoDB
は外部キーをドロップする為の ALTER
TABLE
の利用もサポートします。
ALTER TABLEtbl_name
DROP FOREIGN KEYfk_symbol
;
もし外部キーを作成した時に FOREIGN
KEY
条項が CONSTRAINT
名を含んでいたら、外部キーをドロップする為にその名前を参照する事ができます。そうでなければ、fk_symbol
値は外部キーが作成された時に
InnoDB
によって内部的に生成されます。
外部キーをドロップしたい時にシンボル値を見つけるには、SHOW
CREATE TABLE
ステートメントを利用してください。例:
mysql>SHOW CREATE TABLE ibtest11c\G
*************************** 1. row *************************** Table: ibtest11c Create Table: CREATE TABLE `ibtest11c` ( `A` int(11) NOT NULL auto_increment, `D` int(11) NOT NULL default '0', `B` varchar(200) NOT NULL default '', `C` varchar(175) default NULL, PRIMARY KEY (`A`,`D`,`B`), KEY `B` (`B`,`C`), KEY `C` (`C`), CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11a` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`) REFERENCES `ibtest11a` (`B`, `C`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=INNODB CHARSET=latin1 1 row in set (0.01 sec) mysql>ALTER TABLE ibtest11c DROP FOREIGN KEY `0_38775`;
単一 ALTER TABLE
ステートメントの別々の条項の中に外部キーを追加したりドロップしたりはできません。別々のステートメントが要求されます。
InnoDB
パーサは、FOREIGN KEY
... REFERENCES ...
条項内のテーブルとカラム識別子がバックフォート内で参照される事を許容します。(あるいは、もし
ANSI_QUOTES
SQL
モードが有効であれば二重引用符を利用する事もできます。)InnoDB
パーサは、lower_case_table_names
システム変数の設定も考慮します。
InnoDB
はテーブルの外部キー定義を SHOW CREATE
TABLE
ステートメントのアウトプットの一部として返します:
SHOW CREATE TABLE tbl_name
;
mysqldump はダンプ ファイルのテーブルの正しい定義も作成し、外部キーの事も忘れません。
次のようにテーブルの外部キー制約を表示する事もできます:
SHOW TABLE STATUS FROMdb_name
LIKE 'tbl_name
';
外部キー制約はアウトプットの
Comment
カラム内にリストされています。
外部キー
チェックを行っている時、InnoDB
はそれが見なければいけない子または親レコード上に共有行レベル
ロックを設定します。 InnoDB
は直ちに外部キー制約を確認します。その確認はトランザクション
コミットに据え置きされません。
外部キー関係を持つテーブルのダンプ
ファイルの再ロードを簡単にする為に、mysqldump
は FOREIGN_KEY_CHECKS
を0に設定する為に自動的にダンプ
アウトプット内にステートメントを含みます。これは、ダンプが再ロードされた時にテーブルが特定の順番で再ロードされなければいけないという問題を防ぎます。この変数をマニュアルで設定する事も可能です:
mysql>SET FOREIGN_KEY_CHECKS = 0;
mysql>SOURCE
mysql>dump_file_name
;SET FOREIGN_KEY_CHECKS = 1;
これは、もしダンプ
ファイルが外部キーに対して正しい順番でオーダされていないテーブルを含んでいたら、テーブルをどんな順番でインポートしてもよいと許容します。これはインポート操作のスピードも上げます。FOREIGN_KEY_CHECKS
を0に設定する事は、LOAD DATA
と
ALTER TABLE
操作の最中に外部キー制約を無視する為にも役に立ちます。しかし、FOREIGN_KEY_CHECKS=0
であったとしても、InnoDB
は、カラムが非適合カラム
タイプの参照をつける外部キー制約の作成を許容しません。
InnoDB
は、SET
FOREIGN_KEY_CHECKS=0
を行わない限り、FOREIGN KEY
制約によって参照を付けられたテーブルをドロップする事を許容しません。テーブルをドロップする時、その作成ステートメント内で定義された制約もまたドロップされます。
それは、もしドロップされたテーブルを再作成すると、それに参照をつける外部キー制約と同一の定義を持つはずです。それは右側のカラム名とタイプを持ち、先に述べたように参照キー上にインデックスを持つはずです。もしそれらが満たされなければ、MySQL はエラー番号1005を返し、エラー メッセージ内で errno 150を参照します。