日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL中外键的定义、作用、添加和删除

發(fā)布時間:2023/12/20 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL中外键的定义、作用、添加和删除 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 簡介

在實際開發(fā)的項目中,一個健壯數(shù)據(jù)庫中的數(shù)據(jù)一定有很好的參照完整性。例如學(xué)生檔案和成績單兩張表,如果成績單中有張三的成績,學(xué)生檔案中張三的檔案卻被刪除了,這樣就會產(chǎn)生垃圾數(shù)據(jù)或者錯誤數(shù)據(jù)。為了保證數(shù)據(jù)的完整性,將兩張表之間的數(shù)據(jù)建立關(guān)系,因此就需要在成績表中添加外鍵約束。

2?? ?外鍵的定義
外鍵是指引用另外一個表中的一列或多列數(shù)據(jù),被引用的列應(yīng)該具有主鍵約束或者唯一性約束。外鍵用來建立和加強兩個表數(shù)據(jù)之間的連接。

3?? ?材料準(zhǔn)備
mysql> create table grade(
? ? -> id int(4) not null primary key,
? ? -> name varchar(36)
? ? -> );
Query OK, 0 rows affected (1.14 sec)
?
上表為班級表。

mysql> drop table student;
Query OK, 0 rows affected (0.41 sec)

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| grade ? ? ? ? ?|
+----------------+
1 row in set (0.00 sec)

mysql> create table student (
? ? -> sid int(4) not null primary key,
? ? -> sname varchar(36),
? ? -> gid int(4) not null
? ? -> );
Query OK, 0 rows affected (0.44 sec)
?
上述的代碼片段則是首先刪除在本數(shù)據(jù)庫中的student表,然后創(chuàng)建student表。
首先建立兩張表,student和grade,學(xué)生表中的gid是學(xué)生所在的班級id,是引入了班級表grade中的主鍵id。那么gid就可以作為表student表的外鍵。被引用的表,即表grade是主表,引用外鍵的表,即student,是從表。兩個表是主從關(guān)系。表student用gid可以連接表grade中的信息,從而建立了兩個表中的連接。
可以這么理解,外鍵即依賴關(guān)系,可以明確的聲明表和表之間的關(guān)系額字段的參照關(guān)系,這種就叫做表和表之間聲明了一個外鍵。

注意:引入外鍵之后,外鍵列只能插入?yún)⒄樟写嬖诘闹?#xff0c;參照列被參照的值不能被刪除,這就保證了數(shù)據(jù)的參照完整性。

4?? ?外鍵的添加和刪除
4.1?? ?添加外鍵
為表添加外鍵約束的語法格式如下:

alert table 表名 add constraint FK_ID foreign key(外鍵字段名) references 外表表名(主鍵字段名)
?
其中FK_ID為外鍵的名稱,是隨意的。
為表student添加外鍵約束,具體語句如下:

mysql> alter table student add constraint FK_ID foreign key gid references grade id;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'references grade id' at line 1
mysql> alter table student add constraint FK_ID foreign key (gid) references grade (id);
Query OK, 0 rows affected (1.27 sec)
?
語句執(zhí)行成功后,使用DESC語句來查看學(xué)生表和班級表,查詢結(jié)果如下:

mysql> desc grade;
+-------+-------------+------+-----+---------+-------+
| Field | Type ? ? ? ?| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id ? ?| int(4) ? ? ?| NO ? | PRI | NULL ? ?| ? ? ? |
| name ?| varchar(36) | YES ?| ? ? | NULL ? ?| ? ? ? |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.06 sec)

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type ? ? ? ?| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| sid ? | int(4) ? ? ?| NO ? | PRI | NULL ? ?| ? ? ? |
| sname | varchar(36) | YES ?| ? ? | NULL ? ?| ? ? ? |
| gid ? | int(4) ? ? ?| NO ? | MUL | NULL ? ?| ? ? ? |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
?
可以從上述的輸出中看出表grade中id為主鍵,student表中g(shù)id為外鍵,但是結(jié)果不能明確的看出兩個表之間的關(guān)系。在MySQL中可以用show create table來查看表的詳細(xì)結(jié)構(gòu),具體語句如下:

mysql> show create table student;
+---------+------------------------------------------------------------
| Table ? | Create Table
+---------+------------------------------------------------------------
| student | CREATE TABLE `student` (
? `sid` int(4) NOT NULL,
? `sname` varchar(36) DEFAULT NULL,
? `gid` int(4) NOT NULL,
? PRIMARY KEY (`sid`),
? KEY `FK_ID` (`gid`),
? CONSTRAINT `FK_ID` FOREIGN KEY (`gid`) REFERENCES `grade` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+------------------------------------------------------------
1 row in set (0.06 sec)
?
4.2?? ?驗證外鍵的作用
mysql> insert into student (sid, sname, gid) values(1000, 'wusong', 123);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `FK_ID` FOREIGN KEY (`gid`) REFERENCES `grade` (`id`))
1
2
上述錯誤表示,若要向student中插入學(xué)生數(shù)據(jù),則必須插入已經(jīng)在grade中存在的gid值,實際意義就是要把新來的學(xué)生放入某個班級,則班級必須先存在。

mysql> insert grade values(10, '一班');
Query OK, 1 row affected (0.16 sec)

mysql> insert grade values(11, '二班');
Query OK, 1 r,ow affected (0.12 sec)

mysql> insert grade values('', 1);
ERROR 1366 (HY000): Incorrect integer value: '' for column 'id' at row 1
mysql> insert grade values(12, 1); ?//可見整數(shù)1可以自動轉(zhuǎn)換為varchar1
Query OK, 1 row affected (0.09 sec)
mysql> select * from grade;
+----+--------+
| id | name ? |
+----+--------+
| 10 | 一班 ? |
| 11 | 二班 ? |
| 12 | 1 ? ? ?|
+----+--------+
3 rows in set (0.00 sec)
?
通過插入語句,已經(jīng)向grade中插入了三個班級。向班級1中插入數(shù)據(jù)和班級2中插入。學(xué)生記錄維持在表student中。

mysql> insert into student(sid, sname, gid) values(1000, '周華健', 10);
Query OK, 1 row affected (0.11 sec)

mysql> insert into student(sid, sname, gid) values(1001, '周芷若', 10);
Query OK, 1 row affected (0.17 sec)

mysql> insert into student(sid, sname, gid) values(1002, '周杰倫', 10);
Query OK, 1 row affected (0.19 sec)
以同樣的方式向班級2中插入兩條數(shù)據(jù)
mysql> insert into student(sid, sname, gid) values(10003, '趙云', 11), (10004, '趙子龍', 11);
Query OK, 2 rows affected (0.12 sec)
Records: 2 ?Duplicates: 0 ?Warnings: 0
?
可以插入gid不存在的班級嗎?

mysql> insert into student(sid, sname, gid) values(10003, '趙云', 0);
ERROR 1062 (23000): Duplicate entry '10003' for key 'PRIMARY'
mysql> insert into student(sid, sname, gid) values(10004, '趙云', 0);
ERROR 1062 (23000): Duplicate entry '10004' for key 'PRIMARY'
mysql> insert into student(sid, sname, gid) values(10005, '趙云', 0);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `FK_ID` FOREIGN KEY (`gid`) REFERENCES `grade` (`id`))
?
上述的代碼片段中演示了插入數(shù)據(jù)時外鍵所起的作用,那么刪除時外鍵依然會外參照完整性提供保護。

mysql> select * from grade;
+----+--------+
| id | name ? |
+----+--------+
| 10 | 一班 ? |
| 11 | 二班 ? |
| 12 | 1 ? ? ?|
+----+--------+
3 rows in set (0.00 sec)

mysql> select * from student;
+-------+-----------+-----+
| sid ? | sname ? ? | gid |
+-------+-----------+-----+
| ?1000 | 周華健 ? ?| ?10 |
| ?1001 | 周芷若 ? ?| ?10 |
| ?1002 | 周杰倫 ? ?| ?10 |
| 10003 | 趙云 ? ? ?| ?11 |
| 10004 | 趙子龍 ? ?| ?11 |
+-------+-----------+-----+
5 rows in set (0.00 sec)
?
如果此時要直接刪除grade中的班級1會發(fā)生什么?

mysql> delete from grade where id=10;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`student`, CONSTRAINT `FK_ID` FOREIGN KEY (`gid`) REFERENCES `grade` (`id`))
mysql> delete from grade where id=12;
Query OK, 1 row affected (0.16 sec)
?
上述代碼片段id為10在刪除記錄時彈出了Error,而刪除id為12的記錄時可以成功執(zhí)行,是因為在student表中有依賴id=10的記錄存在,因此無法刪除。

4.3?? ?外鍵關(guān)聯(lián)表聯(lián)合刪除
建立外鍵是為了保證數(shù)據(jù)的完整和統(tǒng)一性,但如果主表中的數(shù)據(jù)被刪除或修改,從表中的數(shù)據(jù)該怎么辦?很明顯應(yīng)該刪除,否則數(shù)據(jù)庫中會存在很多無意義的垃圾數(shù)據(jù)。為此,MySQL可以在建立外鍵時添加ON DELETE或ON UPDATE子句來告訴數(shù)據(jù)庫,怎樣避免垃圾數(shù)據(jù)的產(chǎn)生。

alter table 表名 add constraint FK_ID foreign key (外鍵字段名) references 外表表名 (主鍵字段名)
[on delete {cascade | set null | no action| restrict}]
[on update {cascade | set null | no action| restrict}]
?
其中restrict是默認(rèn)操作,表示拒絕主表刪除或修改外鍵關(guān)聯(lián)列,這是最安全的設(shè)置。
而cascade表示刪除包含與已刪除鍵值有參考關(guān)系的所有記錄。

4.4?? ?刪除外鍵約束
在實際開發(fā)中,根據(jù)業(yè)務(wù)邏輯的需求,需要解除兩個表之間的關(guān)聯(lián)關(guān)系時,就需要刪除外鍵約束。刪除外鍵約束的語法如下:

alter table 表名 drop foreign key 外鍵名;
1
如果解除student表的外鍵約束,具體語句如下:

mysql> show create table student;
+---------+--------------------------------------------------------------
| Table ? | Create Table
+---------+--------------------------------------------------------------
| student | CREATE TABLE `student` (
? `sid` int(4) NOT NULL,
? `sname` varchar(36) DEFAULT NULL,
? `gid` int(4) NOT NULL,
? PRIMARY KEY (`sid`),
? KEY `FK_ID` (`gid`),
? CONSTRAINT `FK_ID` FOREIGN KEY (`gid`) REFERENCES `grade` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+--------------------------------------------------------------
1 row in set (0.00 sec)

mysql> alter table student drop foreign key FK_ID;
Query OK, 0 rows affected (0.19 sec)
Records: 0 ?Duplicates: 0 ?Warnings: 0
?
此時表grade和student的參照關(guān)系便被移除了,

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type ? ? ? ?| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| sid ? | int(4) ? ? ?| NO ? | PRI | NULL ? ?| ? ? ? |
| sname | varchar(36) | YES ?| ? ? | NULL ? ?| ? ? ? |
| gid ? | int(4) ? ? ?| NO ? | MUL | NULL ? ?| ? ? ? |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> insert into student (sid, sname, gid) values (1003, '劉亦菲', 5);
Query OK, 1 row affected (0.13 sec)

mysql> delete from student where id=10;
ERROR 1054 (42S22): Unknown column 'id' in 'where clause'
mysql> delete from grade where id=10; //此時student表中存在gid為10的記錄
Query OK, 1 row affected (0.13 sec)

mysql> show create table student;
+---------+------------------------------------------------------
| Table ? | Create Table
+---------+------------------------------------------------------
| student | CREATE TABLE `student` (
? `sid` int(4) NOT NULL,
? `sname` varchar(36) DEFAULT NULL,
? `gid` int(4) NOT NULL,
? PRIMARY KEY (`sid`),
? KEY `FK_ID` (`gid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+---------+------------------------------------------------------
1 row in set (0.00 sec)

mysql> insert into student (sid, sname, grade^C
mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type ? ? ? ?| Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| sid ? | int(4) ? ? ?| NO ? | PRI | NULL ? ?| ? ? ? |
| sname | varchar(36) | YES ?| ? ? | NULL ? ?| ? ? ? |
| gid ? | int(4) ? ? ?| NO ? | MUL | NULL ? ?| ? ? ? |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
?
由于參照關(guān)系被移除了,則插入student表或者刪除表grade記錄則不再存在參照依賴關(guān)系了,由上述的代碼片段可以看到結(jié)果。

5?? ?總結(jié)
在多表查詢中,外鍵是參照關(guān)系的提現(xiàn),而明確的理解外鍵關(guān)系的含義,了解外鍵關(guān)系的添加和刪除對于mysql數(shù)據(jù)庫表之間的關(guān)系,對增強數(shù)據(jù)庫表設(shè)計的理解,是程序員增強數(shù)據(jù)結(jié)構(gòu)存儲的必備知識儲備。
?————————————————?
?

總結(jié)

以上是生活随笔為你收集整理的MySQL中外键的定义、作用、添加和删除的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。