本文內容: 什麼是外鍵 外鍵的增加 外鍵的修改和刪除 外鍵的約束模式 首發日期:2018-04-12 什麼是外鍵: 外鍵就是表中存在一個欄位指向另外一個表的主鍵,那麼這個欄位就可以稱為外鍵。 一張表可以有多個外鍵。 外鍵用於約束表與表之間的關係,可以說外鍵是表之間的映射關係,這個關係可以幫助我們處理... ...
本文內容:
- 什麼是外鍵
- 外鍵的增加
- 外鍵的修改和刪除
- 外鍵的約束模式
首發日期:2018-04-12
什麼是外鍵:
- 外鍵就是表中存在一個欄位指向另外一個表的主鍵,那麼這個欄位就可以稱為外鍵。
- 一張表可以有多個外鍵。
- 外鍵用於約束表與表之間的關係,可以說外鍵是表之間的映射關係,這個關係可以幫助我們處理表之間關係的緊密性和存在性(比如學生表的cid班級號不能為不存在的,如果不增加外鍵cid,沒有建立上關係,我們就不知道班級號不存在。)。
- 或者說,外鍵是告訴資料庫系統,我們所認為的關係,單純的數據,系統是不知道實際意義的,外鍵就是告訴系統應該如何處理他們的關係。
- 所以,外鍵的核心是約束。
外鍵的增加:
- 創建外鍵的前提是該欄位首先是一個索引,如果不是的話,創建外鍵是會創建成一個普通索引【所以可以不在意】。
- 創建外鍵的另外一個前提是“指向表”已經創建,對於一個不存在的表,將無法使用外鍵對應上。
- 增加的方式:
create table student( id int primary key auto_increment, name varchar(15) not null, gender varchar(10) not null, cid int, foreign key(cid) references class(id) );
create table class( id int primary key auto_increment, cname varchar(15) );
補充:
- 在Mysql中,如果存儲引擎不是innodb,那麼無法使外鍵的約束作用生效,即使是能成功增加外鍵。
- 外鍵名不能重覆,所以不建議使用constraint 外鍵名字
外鍵的修改與刪除:
- 修改:不能修改外鍵信息,如外鍵指向之類的,只能先刪除再新增。
- 刪除語法:alter table 表名 drop foreign key 外鍵名;
補充:
- 刪除外鍵時,如果使用desc會看到表結構還有MUL,那是一個索引。因為創建外鍵時,欄位會被創建成一個索引。如果不想保留,可以使用drop index 欄位名 on 表名.
外鍵的約束模式:
- 外鍵是用來約束表之間的關係的。
- (約定創建外鍵的表稱為子表,指向的表稱為父表)
- 針對子表:可以約束父表的插入和修改【這種約束是父表對子表的約束】
- 針對父表:可以約束父表的刪除和更新,通常有可以一下幾種約束模式。【這種約束是子表對父表的約束】
- 模式:
- strict嚴格模式:涉及到外鍵的刪除和更新時,如果對應記錄的主鍵數據已經被子表使用時,那麼無法刪除(像已經有人入學了某個班級,學校不可能犯傻去把某個班級刪除,只能刪除那些沒人入學的班級。)
- 級聯模式:涉及到外鍵的刪除和更新時,如果欄位已經被子表使用,子表中的數據會對應更新(像某個班改了班號,那麼學生表中的班別都對應更改;如果某個班被刪除,就刪除對應班的所有學生)
- 置空模式:涉及到外鍵的刪除和更新時,如果欄位已經被子表使用,那麼子表中的外鍵數據會置空(像某個班被刪掉了,不應該刪掉所有學生,而是應該給他們先置空再重新分配班別)【子表允許置空的前提是該欄位允許為空】
- 其實可以給不同操作指定不同模式
- 綜上所述(根據我的那些舉例),實際上,合適的舉措是刪除時置空(即使某個班太垃圾了,想刪除某個班,但也不應該將所有學生退學,而是將它們分到別的班),修改時級聯(允許更改班號,而且更改會更新到學生中)
- 不同操作設置不同模式的設置方法(在子表中操作):foreign key(外鍵欄位) references 父表(主鍵) on 操作 模式
foreign key(外鍵欄位) references 父表 (主鍵) on delete set null on update cascade;
-- 實驗表結構 create table class( id int primary key auto_increment, cname varchar(15) ); create table student2( id int primary key auto_increment, name varchar(15) not null, gender varchar(10) not null, cid int, foreign key(cid) references class(id) on delete set null on update cascade ); -- 實驗表數據: insert into class(cname) values("python"),("linux"),("java"),("html5"); insert into student2(name,gender,cid) values("Alice","female",1); insert into student2(name,gender,cid) values("John","female",2); insert into student2(name,gender,cid) values("Jack","female",3); insert into student2(name,gender,cid) values("Amy","female",4); select * from student2; select * from class; -- 嘗試更新級聯 update class set id = 6 where cname="python"; select * from student2; -- 結果原來的python的cid=6 -- 嘗試刪除置空 delete from class where cname="java"; select * from student2; -- 結果原來的java的cid=null
補充:
- 需要設置好約束模式,不要在多個子表中使用不同的約束模式,不然會衝突。