MySQL中外鍵的定義、作用、添加和刪除

1 簡介

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

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

3?? ?材料準備
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)
?
上述的代碼片段則是首先刪除在本數據庫中的student表,然后創建student表。
首先建立兩張表,student和grade,學生表中的gid是學生所在的班級id,是引入了班級表grade中的主鍵id。那么gid就可以作為表student表的外鍵。被引用的表,即表grade是主表,引用外鍵的表,即student,是從表。兩個表是主從關系。表student用gid可以連接表grade中的信息,從而建立了兩個表中的連接。
可以這么理解,外鍵即依賴關系,可以明確的聲明表和表之間的關系額字段的參照關系,這種就叫做表和表之間聲明了一個外鍵。

注意:引入外鍵之后,外鍵列只能插入參照列存在的值,參照列被參照的值不能被刪除,這就保證了數據的參照完整性。

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)
?
語句執行成功后,使用DESC語句來查看學生表和班級表,查詢結果如下:

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表中gid為外鍵,但是結果不能明確的看出兩個表之間的關系。在MySQL中可以用show create table來查看表的詳細結構,具體語句如下:

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中插入學生數據,則必須插入已經在grade中存在的gid值,實際意義就是要把新來的學生放入某個班級,則班級必須先存在。

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); ?//可見整數1可以自動轉換為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)
?
通過插入語句,已經向grade中插入了三個班級。向班級1中插入數據和班級2中插入。學生記錄維持在表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中插入兩條數據
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`))
?
上述的代碼片段中演示了插入數據時外鍵所起的作用,那么刪除時外鍵依然會外參照完整性提供保護。

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會發生什么?

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的記錄時可以成功執行,是因為在student表中有依賴id=10的記錄存在,因此無法刪除。

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

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是默認操作,表示拒絕主表刪除或修改外鍵關聯列,這是最安全的設置。
而cascade表示刪除包含與已刪除鍵值有參考關系的所有記錄。

4.4?? ?刪除外鍵約束
在實際開發中,根據業務邏輯的需求,需要解除兩個表之間的關聯關系時,就需要刪除外鍵約束。刪除外鍵約束的語法如下:

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的參照關系便被移除了,

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)
?
由于參照關系被移除了,則插入student表或者刪除表grade記錄則不再存在參照依賴關系了,由上述的代碼片段可以看到結果。

5?? ?總結
在多表查詢中,外鍵是參照關系的提現,而明確的理解外鍵關系的含義,了解外鍵關系的添加和刪除對于mysql數據庫表之間的關系,對增強數據庫表設計的理解,是程序員增強數據結構存儲的必備知識儲備。
?————————————————?
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456496.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456496.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456496.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Hive報錯:Error: FUNCTION 'NUCLEUS_ASCII' already exists. (state=X0Y68,code=30000)

Hive執行schematool -initSchema -dbType derby報錯。 報錯的日志: doupeihuadoupeihua-2104 ~/software/hive/bin $ schematool -initSchema -dbType derbySLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/doupei…

Andorid Scrolling Activity(CoordinatorLayout詳情)

1.new project -> Scrolling Activity 2.Layout xml code activity_scrolling.xml 1 <?xml version"1.0" encoding"utf-8"?>2 <android.support.design.widget.CoordinatorLayout xmlns:android"http://schemas.android.com/apk/res/an…

截取utf8中文字符串

英文直接截取即可。 中文應字節長度會亂碼&#xff0c;應先轉unicode截取。 如下&#xff1a; #-*- coding:utf8 -*- s u截取中文 s.decode(utf8)[0:3].encode(utf8)轉載于:https://www.cnblogs.com/BigFishFly/p/6337183.html

解決:Navicat for mysql 設置外鍵出錯

1 看下是不是外鍵允許為空&#xff0c;不唯一等約束條件不滿足 2 或者外鍵設置刪除時為 restrict 1. 兩個字段的類型或者大小不嚴格匹配。例如&#xff0c;如果一個是int(10)&#xff0c;那么外鍵也必須設置成int(10)&#xff0c;而不是int(11)&#xff0c;也不能是tinyint。另…

Python加鹽加密方法hashlib(md5,sha224,sha1,sha256)

用random.randint隨機數給密碼加,鹽加強密碼的安全性

Ubuntu16.04以root身份登入!

首先以非root用戶身份登入系統。 1&#xff0c;修改root密碼&#xff1a;啟動shell&#xff0c;隨后在shell里面輸入命令&#xff1a; sudo passwd root 最后輸入root要使用的密碼&#xff0c;需要輸入兩次&#xff0c;這樣root密碼就修改完畢了&#xff01; 2&#xff0c;修改…

HDU2193-AVL-數據結構-AVL

題目鏈接&#xff1a;http://acm.hdu.edu.cn/statistic.php?pid2193&from126&lang&order_type0 好吧。水題一道&#xff0c;原本以為是一道寫AVL樹的想寫來練練手。沒有想到卻是這樣一道水題&#xff0c;好吧&#xff0c;猥瑣的水過。 題目意思&#xff1a; 題目大…

玩Linux碰到的問題以及使用技巧總結

文章目錄1、問題問題一&#xff1a;解壓JDK報錯&#xff1a;gzip:stdin:not in gzip format。 問題二&#xff1a;在Linux下ping不通外網 問題三&#xff1a;解決虛擬機克隆后網卡eth0不見的問題 問題四&#xff1a;執行腳本報錯&#xff1a;syntax error: unexpected end of f…

python連接MySQL數據庫搭建簡易博客

實現功能大概 將python和MySQL數據庫交互進行 封裝 ---》》utils.py 文件程序 ----》blog.py # -*- coding: utf-8 -*- # Time : 2019/08/30 15:33 # Author : Liu # File : utils.pyimport pymysql import hashlibclass dbHelper:def __init__(self, host, user, pass…

利用Sqoop在數據庫和Hive、HDFS之間做ETL操作

文章目錄[toc] 目錄&#xff1a;一、利用Sqoop&#xff0c;從Oracle到HDFS二、利用Sqoop&#xff0c;從Oracle到Hive三、遇到的問題目錄&#xff1a; 一、利用Sqoop&#xff0c;從Oracle到HDFS 第一步&#xff1a;把Oracle驅動拷貝到Sqoop安裝路徑中的lib文件夾下。 第二步&…

跨地域的VPC私網互通【高速通道案例】

最近一家大型企業正在將業務遷移至阿里云平臺&#xff0c;用戶有深圳&#xff0c;北京&#xff0c;上海等分支&#xff0c;其中上海為總部&#xff0c;用戶要求在阿里云上的華南1&#xff0c;華北2&#xff0c;華東2分別建立VPC網絡&#xff0c;其中華南1&#xff0c;華北2要與…

HDU 1711 Number Sequence(KMP模板)

http://acm.hdu.edu.cn/showproblem.php?pid1711 這道題就是一個KMP模板。 1 #include<iostream> 2 #include<cstring>3 using namespace std;4 5 const int maxn 10000005;6 7 int n,m;8 9 int next[maxn]; 10 int a[maxn], b[maxn]; 11 12 void get_next() 13…

Redis數據庫學習筆記

一、NoSql&#xff08;非關系型數據庫&#xff09; NoSQL&#xff1a;NoSQL Not Only SQL 非關系型數據庫 ? NoSQL&#xff0c;泛指非關系型的數據庫。隨著互聯網web2.0網站的興起&#xff0c;傳統的關系數據庫在應付web2.0網站&#xff0c;特別是超大規模和高并發的SNS類型…

Sqoop的安裝配置及工作機制

文章目錄[toc] 目錄&#xff1a;1、簡介2、sqoop安裝2.1、下載并解壓2.2、修改配置文件2.3、加入mysql或oracle的jdbc驅動包2.4、驗證啟動3、Sqoop的原理3.1、代碼定制目錄&#xff1a; 1、簡介 sqoop是apache旗下一款“Hadoop和關系數據庫服務器之間傳送數據”的工具。 導入…

3D打印技術在醫療領域能做些什么?幫助精確完成手術

3D打印技術出現在20世紀90年代中期。它與普通打印工作原理基本相同&#xff0c;打印機內裝有液體或粉末等“打印材料”&#xff0c;與電腦連接后&#xff0c;通過電腦控制把“打印材料”一層層疊加起來&#xff0c;最終把計算機上的藍圖變成實物。這打印技術稱為3D立體打印技術…

【一些簡單的jQuery選擇器】

學習【js DOM 編程藝術】&#xff0c;最后面有許多jQuery的選擇器&#xff0c;每個都動手敲了一遍。 jQuery 提供了高級選擇器的方法。 js獲取元素的三個基本方法分別是通過標簽名&#xff0c;類名和id&#xff0c;即(getElementsByTagName, getElementsByClassName和getElemen…

pymysql操作mysql數據庫

一、pymysql操作mysql數據庫 安裝pymysql pip install pymysql 1.1 pymysql操作數據庫的五行拳 連接數據庫 使用Connect方法連接數據庫 pymysql.Connections.Connection(hostNone, userNone, password, databaseNone, port0, charset) 參數說明&#xff1a;host – 數據庫服務…

SecureCRT常用的使用技巧

文章目錄前言&#xff1a;1、SecureCRT 超時自動斷開連接的解決辦法2、SecureCRT連接Linux時&#xff0c;終端顯示亂碼的問題。3、SecureCRT使用自動記錄日志功能4、使用SecureCRT從Windows上傳文件到Linux5、SecureCRT配色推薦和永久設置前言&#xff1a; 由于工作需要&#…

解決:(1062, Duplicate entry '2019-08-30' for key 'rdate')

解決(1062, "Duplicate entry 2019-08-30 for key rdate") 顯然這個問題是因為插入重復主鍵導致從庫不工作了&#xff0c;更改庫的唯一限制&#xff1a; unique 為normal 或者刪除unique ALTER TABLE 表明 DROP INDEX 字節名; 實例 CREATE TABLE good_booked (au…

人民幣數字金額轉大寫金額

public class t {public static String Trans2RMB(String money) {int index money.indexOf(".");if (index < 0) {// 沒有角分money money ".00";index money.indexOf(".");}if (money.substring(index, money.length()).length() < …