概念:
為了保證數(shù)據(jù)的完整性和一致性,MySQL提供了約束這個(gè)屬性。約束分為表級(jí)約束和列級(jí)約束,如果約束只是針對(duì)某一個(gè)字段來(lái)說(shuō),則稱之為列級(jí)約束,如果針對(duì)兩個(gè)或者兩個(gè)以上的,則稱之為表級(jí)約束。列級(jí)約束既可以在列定義時(shí)聲明,也可以在列定義后聲明,而表級(jí)約束只能在列定義后聲明。
約束類型包括以下幾種:
NOT NULL (非空約束)
PRIMARY KEY (主鍵約束)
UNIQUE KEY (唯一約束)
DEFAULT (默認(rèn)約束)
FOREIGN KEY (外鍵約束)
場(chǎng)景:
在操作數(shù)據(jù)表時(shí),為了避免插入重復(fù)的數(shù)據(jù),可以在字段后面添加 AUTO_INCREMENT(自動(dòng)編號(hào)) 屬性來(lái)保證記錄的唯一性,并且該字段必須為整型或者字符型,若使用字符型,小數(shù)必須為 0 。
該屬性如下特點(diǎn):
⑴ 賦予自動(dòng)編號(hào)屬性的字段必須定義為主鍵
⑵ 在默認(rèn)情況下,起始值為1,每次遞增加1
案例:

創(chuàng)建一張 tb_test2 數(shù)據(jù)表,并且給 id 字段賦予 AUTO_INCREMENT 屬性,系統(tǒng)報(bào)錯(cuò),根據(jù)信息可以看出,字段 id 必須設(shè)置為主鍵。接下來(lái)我們來(lái)了解一下主鍵約束和其他約束。(非空約束在上一文結(jié)尾已提及)
1、主鍵約束 (PRIMARY KEY)
特點(diǎn):
⑴ 每張數(shù)據(jù)表只能存在一個(gè)主鍵
⑵ 主鍵可以保證記錄的唯一性
⑶ 主鍵自動(dòng)默認(rèn)為 NOT NULL
案例:

以剛才創(chuàng)建的表為例,重新創(chuàng)建數(shù)據(jù)表,在 id 后添加 PRIMARY KEY 屬性表示該字段為主鍵。
接著查看數(shù)據(jù)表的結(jié)構(gòu):

可以發(fā)現(xiàn),字段 id 不為 NULL 符合 AUTO_INCREMENT 屬性特點(diǎn),key 的值為 PRI,說(shuō)明該字段為主鍵,而 username 在創(chuàng)建時(shí)已經(jīng)指定為 NOT NULL 。當(dāng)我們依次插入數(shù)據(jù)時(shí),對(duì)應(yīng)的id 會(huì)自動(dòng)增長(zhǎng)。
案例:(數(shù)據(jù)表的記錄操作會(huì)在后續(xù)的文章提及)

依次插入三條記錄,并查看所有記錄,數(shù)據(jù)表的 id 自動(dòng)遞增。
注: AUTO_INCREMENT 必須和 PRIMARY KEY 一起使用,而 PRIMARY KEY 不一定和
AUTO_INCREMENT 一起使用。
案例:


當(dāng)我們創(chuàng)建數(shù)據(jù)表并沒(méi)有給主鍵 id 賦予 AUTO_INCREMENT 時(shí),系統(tǒng)提示創(chuàng)建成功,此時(shí)的 id 不能為空,查詢表結(jié)構(gòu)可以看出 Extra 字段沒(méi)有 auto_increment 屬性。我們插入一些記錄來(lái)驗(yàn)證一下:

在插入記錄時(shí),分別對(duì) id 和 username 字段進(jìn)行賦值,但是不允許插入兩條相同的記錄:

當(dāng)我們插入相同 id 的記錄時(shí),系統(tǒng)報(bào)錯(cuò),提示表已存在該記錄。
在一張數(shù)據(jù)表中,除了主鍵約束外,為了保證記錄的唯一性,MySQL 提供了另一種約束,
就是唯一約束。
2、唯一約束 (UNIQUE KEY)
特點(diǎn):
⑴ 唯一約束可以保證記錄的唯一性
⑵ 唯一約束的字段可以為空值(NULL)
⑶ 每張數(shù)據(jù)表可以存在多個(gè)唯一約束
當(dāng)然了,對(duì)于指定唯一約束的字段來(lái)說(shuō),如果插入的多條記錄都為空,表里也只存在一條空記錄,保證唯一性。
案例:

創(chuàng)建表 tb_test4 ,字段 id 為主鍵且自動(dòng)增長(zhǎng),username 為字符型且唯一約束。
我們插入記錄驗(yàn)證一下:

插入一條記錄提示成功。

重新插入一條相同的記錄,系統(tǒng)報(bào)錯(cuò),不能重復(fù)添加,說(shuō)明 username 被賦予唯一約束,只能插入一條記錄。
3、默認(rèn)約束 (DEFAULT)
特點(diǎn):
當(dāng)插入記錄時(shí),如果沒(méi)有明確為字段賦值,系統(tǒng)自動(dòng)賦予默認(rèn)值
案例:

創(chuàng)建數(shù)據(jù)表 tb_test5 并查看表結(jié)構(gòu),其中,sex 字段含有三個(gè)值,分別對(duì)應(yīng)男、女、保密三種性別,且默認(rèn)值為 3 。

插入一條只給 username 賦值的記錄時(shí) ,查詢記錄,可以發(fā)現(xiàn),字段 sex 的記錄值為 3 ,也就是默認(rèn)值。
4、外鍵約束(FOREIGN KEY)
特點(diǎn):
⑴ 保持?jǐn)?shù)據(jù)一致性,完整性?
⑵ 實(shí)現(xiàn)一對(duì)一或一對(duì)多關(guān)系
要求:
⑴ 父表(字表所參照的表)和子表(具有外鍵列的表)必須使用相同的存儲(chǔ)引擎,而且禁止使用臨時(shí)表。
⑵ 數(shù)據(jù)表的數(shù)據(jù)引擎只能為 InnoDB。
⑶ 外鍵列和參照列必須具有相同的數(shù)據(jù)類型。其中數(shù)字的長(zhǎng)度或是否有符號(hào)位必須相同;
而字符的長(zhǎng)度則可以不同。
⑷ 外鍵列和參照列必須創(chuàng)建索引。如果不存在索引的話,MySQL將自動(dòng)創(chuàng)建索引。
我們通過(guò)以上要求要?jiǎng)?chuàng)建表并賦予外鍵約束。
案例:
首先查看數(shù)據(jù)庫(kù)的默認(rèn)存儲(chǔ)引擎:

由返回結(jié)果看出,MySQL默認(rèn)存儲(chǔ)引擎為 InnoDB 。
現(xiàn)在我們創(chuàng)建兩張表,并對(duì)指定的字段賦予相同的數(shù)據(jù)類型:

創(chuàng)建一張省份表并查看該表的引擎:

由圖可以看出,存儲(chǔ)引擎是 InnoDB 滿足要求。

再創(chuàng)建一張用戶表,含有用戶id,用戶名username ,和用戶所在省份的外鍵 pid ,此時(shí)創(chuàng)建失敗,因?yàn)橥怄I pid 的數(shù)據(jù)類型和父表中的 id 數(shù)據(jù)類型不一致導(dǎo)致無(wú)法創(chuàng)建,同樣,如果外鍵 pid 是否有符號(hào)與父表的主鍵 id 不一致,也是無(wú)法創(chuàng)建成功的。
其中,約束外鍵的語(yǔ)法結(jié)構(gòu)為:
FOREIGN KEY (外鍵 id)REFERENCES 父表名稱 (父表所參照的 id)。

由圖可以得出,外鍵 pid 滿足數(shù)據(jù)類型和是否有符號(hào)和父表主鍵 id 一致,所以該表創(chuàng)建成功。注:外鍵列(pid)和參照列(id)必須創(chuàng)建索引。
我們來(lái)看看兩張表是否有創(chuàng)建索引:

由圖可以看出,數(shù)據(jù)表 tb_province 的參照列 id 已經(jīng)創(chuàng)建了主鍵索引。

而對(duì)于數(shù)據(jù)表 tb_users ,可以發(fā)現(xiàn)存在兩個(gè)索引,一個(gè)是主鍵索引 id,另一個(gè) pid 系統(tǒng)已經(jīng)自動(dòng)創(chuàng)建了索引。

通過(guò)查看所該表的創(chuàng)建命令,可以看出系統(tǒng)給 pid 自動(dòng)創(chuàng)建了索引( KEY 'pid'),同時(shí)在
CONSTRAINT 'tb_users_ibfk_1' FOREIGN KEY ('pid')? 可以得出 pid 為外鍵約束。
在我們創(chuàng)建外鍵約束的時(shí)候,可以添加一些外鍵約束的參照操作,有如下幾種:
⑴ CASCADE:父表刪除或更新行時(shí),同時(shí)自動(dòng)更新或更新子表匹配的行
⑵ SET NULL:從父表刪除或更新行,并設(shè)置子表中的外鍵列為 NULL 。如果使用該選項(xiàng),必須保證子表列沒(méi)有指定 NOT NULL
⑶ RESTRICT:拒絕對(duì)父表的刪除或更新操作
⑷ NO ACTION:標(biāo)準(zhǔn) MySQL 的關(guān)鍵字,在 MySQL 中與 RESTRICT 相同
在更新表的時(shí)候,可以通過(guò)以上選項(xiàng)來(lái)設(shè)置子表是否進(jìn)行相應(yīng)的操作。
案例:

我們創(chuàng)建一張 tb_users1 數(shù)據(jù)表,給 pid 設(shè)置為外鍵約束,同時(shí)在刪除的時(shí)候,設(shè)置 CASCADE 選項(xiàng)。
接下來(lái)通過(guò)插入信息來(lái)驗(yàn)證一下。由于子表(tb_users1)參照父表(tb_province),為了保證子表有參照數(shù)據(jù),必須先在父表里插入記錄。


對(duì)父表(tb_province)依次插入三條記錄,并查詢所有記錄。


對(duì)子表(tb_user1)依次插入三條記錄,并查詢所有數(shù)據(jù)。
現(xiàn)在兩張表都存在記錄,我們先通過(guò)刪除記錄來(lái)驗(yàn)證一下,CASCADE 選項(xiàng)。
首先刪除父表(tb_province)中 id 為 2 的記錄:

查詢 tb_province 所有記錄:

可以看出,原先記錄 id = 2 已經(jīng)被刪除了。
我們?cè)賮?lái)查詢一下子表中 pid = 3 的記錄是否還存在:

由圖可以得知,pid = 2 的所有記錄已經(jīng)被刪除了。
這就是 CASCADE 所起的作用,父表刪除記錄同時(shí)刪除子表所相關(guān)的記錄,同理更新的操作也會(huì)影響子表的記錄。
在實(shí)際開(kāi)發(fā)中,我們很少使用物理的外鍵約束,一般使用邏輯的外鍵約束,因?yàn)槲锢硗怄I約束只有在 InnoDB 引擎下才得以支持,而物理外鍵可以通過(guò)在兩張表中存在某種結(jié)構(gòu)來(lái)定義約束,而不使用 FORENGIEN KEY 這個(gè)關(guān)鍵詞來(lái)定義。
總結(jié):
列級(jí)約束使用比較多,表級(jí)約束很少使用,在以上幾種約束中,NOT NULL 約束,DEFAULT 約束這兩種約束不存在表級(jí)約束,它們只有列級(jí)約束,而對(duì)于其他的三種,PRIMARY KEY 約束,UNIQUE 約束,F(xiàn)ORENGIEN KEY 約束,它們都可以存在表級(jí)和列級(jí)約束。
約束分為以下幾種:
⑴ 功能
? ??① NOT NULL (非空約束)
????② PRIMARY KEY(主鍵約束)
????③ UNIQUE KEY(唯一約束)
????④ DEFAULT(默認(rèn)約束)
????⑤ FROEIGN KEY(外鍵約束)
⑵ 數(shù)據(jù)列的數(shù)目
? ??① 表級(jí)約束
????② 列級(jí)約束
以上為本人的一些學(xué)習(xí)筆記,如有出錯(cuò)歡迎指正,陸續(xù)更新?。?!