MySql多對多關係中外來鍵的應用
業務需求:使用者表r_user儲存使用者名稱等資訊。現需要給每個使用者設定工作基地,一個使用者可以有多個工作基地,多個使用者也可以有一個工作基地,即多對多關係。(外來鍵,若有兩個表A,B,C是A的主鍵,而B中也有C欄位,則C就是表B的外來鍵,外來鍵約束主要用來維護兩個表之間資料的一致性)
設計方案:
方案一:建立一張使用者基地表,與r_user與使用者基地表,保持一對多的關係,如圖所示,r_user的主鍵id做為r_user_base的外來鍵user_id。通過r_user中的id,在r_user_base表中load該使用者的所有工作基地。
方案二:建立一張個基地表base_info儲存目前存在的所有基地,再建一張user_base關係表。如圖所示,關係表user_base有兩個外來鍵user_id與base_id
方案一的特點是,只需要鍵一張表就可以完成業務需求。缺點是不夠模組化,如果在其它地方還要用到基地資訊,則還要再建基地表
方案二的特點是,用一張關係表連線兩張資訊表。便於資訊表的維護與重複利用。
基於業務需求與以後擴充套件及重用性考慮,採用方案二實現需求。
在MySQL 3.23.44版本後,InnoDB引擎型別的表支援了外來鍵約束。
外來鍵的使用條件:
1.兩個表必須是InnoDB表,MyISAM表暫時不支援外來鍵(據說以後的版本有可能支援,但至少目前不支援);
2.外來鍵列必須建立了索引,MySQL 4.1.2以後的版本在建立外來鍵時會自動建立索引,但如果在較早的版本則需要顯示建立;
3.外來鍵關係的兩個表的列必須是資料型別相似,也就是可以相互轉換型別的列,比如int和tinyint可以,而int和char則不可以;
外來鍵的定義語法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
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, 都是立即檢查外來鍵約束
建立人員資訊表:
1 CREATE TABLE `r_user` ( 2 `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 `NAME` varchar(20) DEFAULT NULL, 4 `PASSWORD` varchar(50) DEFAULT NULL, 5 `STAFF_NUM` varchar(20) DEFAULT NULL, 6 `USER_NAME` varchar(20) DEFAULT NULL, 7 PRIMARY KEY (`id`), 8 ) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8
建立基地資訊表
1 CREATE TABLE `branch_info` ( 2 `ID` bigint(20) NOT NULL AUTO_INCREMENT, 3 `BRANCH_CODE` varchar(255) DEFAULT NULL, 4 `BRANCH_DESC` varchar(255) DEFAULT NULL, 5 PRIMARY KEY (`ID`) 6 ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8
關係表:
1 CREATE TABLE `user_work_base` ( 2 `id` bigint(20) NOT NULL AUTO_INCREMENT, 3 `version` int(11) NOT NULL, 4 `user_id` bigint(20) NOT NULL , 5 `base_id` bigint(20) NOT NULL , 6 PRIMARY KEY (`id`), 7 CONSTRAINT `user_work_base_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `r_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 8 CONSTRAINT `user_work_base_ibfk_2` FOREIGN KEY (`base_id`) REFERENCES `branch_info` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE 9 ) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8
刪除人員r_user表中人員A,關係表user_base自動刪除A的關係資料。
如果外來鍵使用Restrict方式,只刪除A,則報錯。
Cannot delete or update a parent row: a foreign key constraint fails (`maircrew`,`user_work_base`, CONSTRAINT `FK41EB46D32AA89EA0`
FOREIGN KEY (`user_id`) REFERENCES `r_user` (`id`))