前書き
外部キーを使用するための条件:
- 2つのテーブルはInnoDBテーブルである必要があります。MyISAMテーブルは一時的に外部キーをサポートしません
- 外部キーカラムにはインデックスを付ける必要があります。MySQL4.1.2以降のバージョンでは、外部キーの作成時にインデックスが自動的に作成されます
- 外部キー関係の2つのテーブルの列は、データ型が類似している必要があります。つまり、intとtinyintなど、相互に変換できるが、intとcharは変換できない列で、関連するフィールドは一意である必要があります。
4種類の外部キー制約
RESTRICT(制約):削除時に表示された場合、外部キーの主キーがレコード(主テーブルのレコード)を直接削除できないことを意味します。制約されたテーブルのdept_idフィールドにあるすべての外部キーの主キーを(テーブルから)削除する必要があります。値に対応するレコードは、外部キー制約を削除できます(メインテーブルのレコード)テストでは、Navicatでデフォルト設定が選択されていないことがわかりました。
アクションなし:これはMySQLのRESTRICTと同等です。理由は次のとおりです。制限は、変更または削除する前にテーブルに対応するデータがあるかどうかを確認することです。ある場合、操作を拒否し、一部のデータベースではアクションがソース標準SQLになります、チェックを遅らせます。つまり、変更または削除後にスレーブテーブルに対応するデータがあるかどうかをチェックします。ある場合、操作を拒否しますが、MySQLでは、外部キー制約がすぐにチェックされるため、2つは同等です
CASCADE:削除このオプションを選択すると、プライマリテーブルのレコードを削除すると、プライマリテーブルのプライマリキーIDに関連付けられたセカンダリテーブルのID値を持つレコードも削除されます。選択しないことをお勧めします。
SET NULL:このオプションを削除するとき、テーブル(制約されたフィールドが配置されているテーブル内)からの制約されたフィールドの値がnullに設定されている場合、メインテーブルのレコードが削除されると、メインテーブルのレコードが削除されますレコードの主キー値(制約されたスレーブテーブルフィールドの値)がスレーブテーブルの対応するフィールドに表示され、レコードの制約されたフィールドの値はNULLになります。
最も一般的に使用されるのは、RESTRICTが削除を許可しない制約を選択するか、SET NULLを選択して値テーブルを削除して空にすることです。
例
ステップ1:2つのテーブル(departmentテーブルdeptおよびemployeeテーブルemp)を作成し、emp.dnoの外部キーをdept.didに関連付けます。
CREATE TABLE `dept` (
`did` int(10) NOT NULL AUTO_INCREMENT,
`dname` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`did`),
UNIQUE KEY `dname` (`dname`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `emp` (
`eid` int(10) NOT NULL AUTO_INCREMENT,
`ename` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
`dno` int(10) DEFAULT NULL,
`sal` double(7,2) DEFAULT NULL,
PRIMARY KEY (`eid`),
KEY `fk_dno_did` (`dno`),
CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
mysql> desc dept;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| did | int(10) | NO | PRI | NULL | auto_increment |
| dname | varchar(255) | NO | UNI | NULL | |
+-------+--------------+------+-----+---------+----------------+
mysql> desc emp;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| eid | int(10) | NO | PRI | NULL | auto_increment |
| ename | varchar(30) | YES | | NULL | |
| dno | int(10) | YES | MUL | NULL | |
| sal | double(7,2) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
ステップ2:テーブルデータを初期化する
insert into dept values (1,'技术部'),(2,'人事部');
insert into emp values (1,'张三',1,10000),(2,'李四',2,20000);
mysql> select * from dept order by did;
+-----+--------+
| did | dname |
+-----+--------+
| 1 | 技术部 |
| 2 | 人事部 |
+-----+--------+
mysql> select * from emp order by eid;
+-----+-------+-----+----------+
| eid | ename | dno | sal |
+-----+-------+-----+----------+
| 1 | 张三 | 1 | 10000.00 |
| 2 | 李四 | 2 | 20000.00 |
+-----+-------+-----+----------+
ステップ3:関連データがある場合、部門データテーブルを削除または更新するか、empの挿入または更新時にエラーを報告します(4つのケース)
delete from dept where did=1;
1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
update dept set did=3 where did=1;
1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
insert into emp values (null,'张三',4,10000);
1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
update emp set dno=3 where eid=1;
1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`emp`, CONSTRAINT `fk_dno_did` FOREIGN KEY (`dno`) REFERENCES `dept` (`did`))
拡張:他の制約タイプ
- 主キー制約PRIMARY KEY
- ユニーク
- NULLでない制約
- デフォルト値制約DEFAULT