外鍵約束
MySQL的外鍵約束用來在兩個表數據之間建立鏈接,其中一張表的一個字段被另一張表中對應的字段約束。也就是說,設置外鍵約束至少要有兩種表,被約束的表叫做從表(子表),另一張叫做主表(父表),屬於主從關係。
其中主表中的關聯字段叫做主鍵,外表中的關聯字段叫做外鍵。
外鍵約束主要作用就是能夠讓表與表之間的數據建立關聯,使數據更加完整,關聯性更強。
關於完整性,可以通過一個例子來說明
假如有兩種表,一張用戶賬戶表(用於存儲用戶賬戶),一張是賬戶信息表(用於存儲賬戶中的信息)。
1)我不小心將用戶賬戶表中的某個用戶刪除了,那麼賬戶信息表中與這個用戶有關的數據就變成無源數據了,找不到其屬於哪個用戶賬戶,導致用戶信息不完整。
2)我在賬戶信息表中隨便添加了一條數據,而其在用戶賬戶表中沒有對應的用戶,這樣用戶信息也是不完整的。
如果有了外鍵約束,將用戶賬戶表設爲主表,賬戶信息表設爲從表,那麼就無法直接往賬戶信息表中插入數據,在用戶賬戶表中刪除用戶,賬戶信息表中的用戶信息也會被刪除。外鍵約束的方式可以使兩張緊密的聯繫在一起,保障數據完整性和一致性的同時,日常維護也更加方便。
外鍵創建規則
1)必須有主表纔可以設置從表。
2)主表必須實際存在。
3)必須爲主表定義主鍵。
4)外鍵列的數據類型必須和主鍵列的數據類型相同。
5)外鍵列的數量必須和主鍵列的數量相同。
6)外鍵可以不是外表中的主鍵,但必須和主表關聯字段相對應。
7)主從表創建時,存儲引擎必須是InnoDB。
創建外鍵約束語法
create table 表名(
字段定義…
CONSTRAINT `外鍵名稱` FOREIGN KEY (字段)REFERENCES 主表名(主鍵字段) 屬性);
參數說明:
CONSTRAINT :用於設置外鍵約束名稱,可以省略
FOREIGN KEY:外鍵設置,用於指定外鍵字段
REFERENCES:主表及主鍵設置,用於指定主表和主鍵
CASCADE:主表刪除或修改記錄時,從表也會對關聯記錄的外鍵字段進行修改。
RESTRICT:刪除或修改主表記錄,子表中若有關聯記錄,則不允許主表刪除或修改。
SET NULL:主表刪除或修改主表記錄時,從表會將關聯記錄的外鍵字段設爲null。
ON UPDATE CASCADE:主表修改記錄時,從表關聯記錄的外鍵字段也會修改。(將CASCADE改爲RESTRICT,意思相反)
ON DELETE CASCADE:主表刪除記錄時,從表關聯記錄的外鍵字段也會刪除。(將CASCADE改爲RESTRICT,意思相反)
外鍵約束創建
創建兩個表,主表爲class,從表爲students
主表:
mysql> create table class(
xuehao int primary key,
name varchar(6))engine=innodb;
從表:
mysql> create table students( 從表
id int auto_increment primary key,
uid int not null,
name varchar(6) not null,
foreign key(uid) references class(xuehao)
on update cascade on delete cascade)engine=innodb;
插入數據,進行測試
mysql> insert into class values(111,'張三'),(222,'李四'),(333,'王五');
mysql> insert into students values(1,111,'張三'),(2,222,'李四'),(3,333,'王五');
查看創建的記錄
mysql> select * from class;
+--------+--------+
| xuehao | name |
+--------+--------+
| 111 | 張三 |
| 222 | 李四 |
| 333 | 王五 |
+--------+--------+
mysql> select * from students;
+----+-----+--------+
| id | uid | name |
+----+-----+--------+
| 1 | 111 | 張三 |
| 2 | 222 | 李四 |
| 3 | 333 | 王五 |
+----+-----+--------+
驗證外鍵約束特性,刪除從表中id爲1的記錄
mysql> delete from students where id=1;
mysql> select * from students;
+----+-----+--------+
| id | uid | name |
+----+-----+--------+
| 2 | 222 | 李四 |
| 3 | 333 | 王五 |
+----+-----+--------+
mysql> select * from class;
+--------+--------+
| xuehao | name |
+--------+--------+
| 111 | 張三 |
| 222 | 李四 |
| 333 | 王五 |
+--------+--------+
從表中刪除記錄不會對主表造成影響。(從刪主不刪)
在主表中刪除學號爲111的記錄
mysql> insert into students values(1,111,'張三'); 將刪除的記錄從新插入
mysql> select * from students;
+----+-----+--------+
| id | uid | name |
+----+-----+--------+
| 1 | 111 | 張三 |
| 2 | 222 | 李四 |
| 3 | 333 | 王五 |
+----+-----+--------+
mysql> delete from class where xuehao=111;
mysql> select * from students;
+----+-----+--------+
| id | uid | name |
+----+-----+--------+
| 2 | 222 | 李四 |
| 3 | 333 | 王五 |
+----+-----+--------+
2 rows in set (0.00 sec)
主表的修改根據屬性會對從表造成影響。(主刪從不見)
mysql> insert into students values(4,444,'趙六');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test2`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `class` (`xuehao`) ON DELETE CASCADE ON UPDATE CASCADE)
無法插入主鍵關聯中不存在的記錄。(class表的xuehao字段中沒有444,所以與其關聯的students表中uid爲444的記錄也無法插入)
只有主表存在,從表纔可插入,解決方案就是給主表插入xuehao爲444的字段。
mysql> insert into class values(444,'趙六');
mysql> insert into students values(4,444,'趙六');
mysql> select * from students;
+----+-----+--------+
| id | uid | name |
+----+-----+--------+
| 2 | 222 | 李四 |
| 3 | 333 | 王五 |
| 4 | 444 | 趙六 |
+----+-----+--------+
修改創建外鍵約束
語法:
alter table 表名 add constraint `外鍵名稱` foreign key (外鍵字段)references 主表(主鍵) 屬性);
將之前的students表刪除,從新創建。
mysql> drop table students;
mysql> create table students(id int primary key auto_increment,uid int not null,name varchar(6) not null);
將其修改爲class表的外鍵約束
mysql> alter table students add foreign key(uid) references class(xuehao) on update cascade on delete cascade;
通過查看錶執行命令,即可查詢外鍵約束是否創建完成
mysql> show create table students\G
*************************** 1. row ***************************
Table: students
Create Table: CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`name` varchar(6) NOT NULL,
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
CONSTRAINT `students_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `class` (`xuehao`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
其中CONSTRAINT `students_ibfk_1`字樣就是外鍵的名稱,沒有手動指定,外鍵名稱是數據庫設置的,在刪除外鍵時會用到外鍵名稱。
刪除外鍵
語法:
alter table 表名 drop foreign key 外鍵名稱;
將創建的外鍵刪除
mysql> alter table students drop foreign key students_ibfk_1;
再次查看創建表的命令,發現與外鍵相關的設置消失了
mysql> show create table students\G
*************************** 1. row ***************************
Table: students
Create Table: CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`name` varchar(6) NOT NULL,
PRIMARY KEY (`id`),
KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
完整格式創建
在之前的舉例創建中,偷懶將可以省略的外鍵名稱設置給省略了,爲外鍵設置一個名稱,在刪除的時候還是比較方便的,系統自動創建的有點長。
刪除原students表
mysql> drop table students;
從新創建,並且建立外鍵
mysql> create table students(
-> id int primary key auto_increment,
-> uid int not null,
-> name varchar(6) not null,
-> constraint `qwq` foreign key (uid) references class(xuehao)
-> on update cascade on delete cascade
-> )engine=innodb;