業務需求:用戶表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`))