MySQL中的外鍵約束(FOREIGN KEY)是什麼?

外鍵約束

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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章