mysql 外來鍵
一、是什麼
從表的某列指向主表的某列,從表的這一列就是從表的外來鍵。
外來鍵不一定要指向主表的主鍵,但必須是唯一性索引。
二、為什麼
外來鍵能保持資料的一致性、完整性。
1、外來鍵約束用於預防破壞表之間連線的行為:在主表上直接update/delete以更新或刪除在從表中有匹配行的外來鍵時,會報錯
2、外來鍵約束也能防止非法資料插入外來鍵列,因為它必須是它指向的主表的列中的值之一:如果在主表列欄位找不到對應的鍵,則不允許在從表上進行insert/update
可以在定義從表外來鍵的時候指定on update/on delete的方式,InnoDB支援5種方式:
. cascade方式
在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄
On delete cascade從mysql3.23.50開始可用; on update cascade從mysql4.0.8開始可用
. set null方式
在父表上update/delete記錄時,將子表上匹配記錄的列設為null
要注意子表的外來鍵列不能為not null
On delete set null從mysql3.23.50開始可用; on update set null從mysql4.0.8開始可用
. No action方式
如果子表中有匹配的記錄,則不允許對父表對應候選鍵進行update/delete操作
這個是ANSI SQL-92標準,從mysql4.0.8開始支援
. Restrict方式 (預設)
同no action, 都是立即檢查外來鍵約束
. Set default方式
解析器認識這個action,但Innodb不能識別,不知道是什麼意思...
注意:trigger不會受外來鍵cascade行為的影響,即不會解發trigger
三、怎麼用
外來鍵的使用條件:
1.兩個表必須是InnoDB表,MyISAM表暫時不支援外來鍵(據說以後的版本有可能支援,但至少目前不支援);
2.外來鍵列必須建立了索引,MySQL 4.1.2以後的版本在建立外來鍵時會自動建立索引,但如果在較早的版本則需要顯示建立;
3.外來鍵關係的兩個表的列必須是資料型別相似,也就是可以相互轉換型別的列,比如int和tinyint可以,而int和char則不可以;
(1)建立表
create table user_info ( user_id int notnull, name varchar (100) not null, primary key (user_id), foreign key (name) references user (name) )
user表的name列並不是user表的主鍵,但是它是唯一的,這樣也可以建立外來鍵。如果被引用的列不是唯一的,則會報錯: Error Code: 1215. Cannot add foreign key constraint
mysql會為user表的name列自動建立一個唯一性索引
也會為user_info表的name列建立一個索引,因為user_info表的name列並不是唯一的,因此不會建立唯一性索引,這也證明從表的外來鍵不一定需要是唯一性索引
在user_info表插入資料時,name欄位的值需要在user的name欄位有對應的值,這是防止非法資料插入外來鍵列。如果沒有則會報錯:
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`mychat`.`user_info`, CONSTRAINT `user_info_ibfk_1` FOREIGN KEY (`name`) REFERENCES `user` (`name`))
如果在user_info的name列有相應資料,無法刪除user中的資料,這是預防破壞表之間連線的行為:
Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`mychat`.`user_info`, CONSTRAINT `user_info_ibfk_1` FOREIGN KEY (`name`) REFERENCES `user` (`name`))
(2)直接新增約束
alter table mychat.user_info add foreign key (user_id) references user(user_id);
(3)撤銷外來鍵約束
alter table mychat.user_info drop foreign key user_info_ibfk_3;