MySQL中常見(jiàn)的六個(gè)約束類型詳解
前言
在向數(shù)據(jù)表中插入數(shù)據(jù)時(shí),有的時(shí)候?qū)τ诓迦氲臄?shù)據(jù)是有特殊要求的,比如學(xué)生成績(jī)不能為空,學(xué)生學(xué)號(hào)不能重復(fù)等等,這個(gè)時(shí)候約束就派上用場(chǎng)了。
約束類型是通過(guò)對(duì)表的行或列的數(shù)據(jù)做出限制,來(lái)確保表的數(shù)據(jù)的完整性、唯一性。這一章我們主要介紹六個(gè)常見(jiàn)的MySQL約束類型。
1. not null
保證指定不能存儲(chǔ)NULL值,如果插入NULL則插入失敗。
我們定義兩張數(shù)據(jù)表,分別是student表和student_copy表,student表設(shè)定相關(guān)約束,student_copy表作為其對(duì)照表,不設(shè)置任何約束來(lái)觀察兩者的區(qū)別。
student表中id定義了not null,所以id這一行的NULL = NO,意思是這一行數(shù)據(jù)不能為NULL,否則會(huì)插入失敗。
student_copy表中沒(méi)有進(jìn)行任何約束,所以任何字段的NULL = YES,意味著用戶可以隨意插入空值而不會(huì)報(bào)錯(cuò)。
Q:not null約束下除了顯式的指定插入NULL會(huì)報(bào)錯(cuò)外,隱式的NULL會(huì)報(bào)錯(cuò)嗎?
NULL指定有兩種方式,分別是顯式和隱式。
顯式指的是插入時(shí)設(shè)定該列為NULL,而隱式指的是插入時(shí)對(duì)該列沒(méi)有賦值,而這一列又沒(méi)有指定默認(rèn)值,系統(tǒng)默認(rèn)的默認(rèn)值是NULL,所有這中情況下也會(huì)觸發(fā)插入控制的錯(cuò)誤。
2. unique
保證某列的每行必須有唯一的值,也就是說(shuō),指定列的每行數(shù)據(jù)都不能重復(fù)。
下面兩張圖分別是對(duì)student表和student_copy表的操作,student表的id列設(shè)置了unique約束,所以在插入同樣的id = 1時(shí)會(huì)顯示重復(fù)操作。
student_copy表中沒(méi)有進(jìn)行任何約束,意味著用戶可以隨意插入任意值而不會(huì)報(bào)錯(cuò)。
Q:unique約束下插入NULL值會(huì)報(bào)錯(cuò)嗎?
其實(shí)這個(gè)問(wèn)題在剛才已經(jīng)操作過(guò)了,student表中插入id = NULL,系統(tǒng)并不會(huì)報(bào)錯(cuò)。unique只是保證存儲(chǔ)的值唯一,它可以是空值,但空值也得唯一,再插入NULL就會(huì)報(bào)錯(cuò)。
3. default
規(guī)定沒(méi)有給列賦值時(shí)的默認(rèn)值,換句話說(shuō)就是,插入數(shù)據(jù)時(shí)沒(méi)有給指定列的值,那么其值就是defalut指定的默認(rèn)值。
student表指定了name字段設(shè)置了default約束之后,default這一列就有了名字。當(dāng)插入數(shù)據(jù)時(shí),沒(méi)有指定name這一列,那么name這列就會(huì)按照我們?cè)O(shè)置的默認(rèn)值 = '未命名'來(lái)填充。
而student_copy表沒(méi)有設(shè)置default約束,所以當(dāng)插入數(shù)據(jù)時(shí),沒(méi)有指定的列會(huì)按照系統(tǒng)默認(rèn)的默認(rèn)值來(lái)填充,也就是NULL。
4. primary key
not null + unique 的結(jié)合,保證某列具有唯一標(biāo)識(shí)且不能存儲(chǔ)NULL值。
前幾個(gè)約束類型都是可以同時(shí)給多個(gè)列設(shè)置的,但是primary key一張表中只有能約束一列,使用primary key約束的列被稱為主鍵。
和unique類型,插入的數(shù)據(jù)如果重復(fù)了,那么后一條數(shù)據(jù)會(huì)插入失敗,并且插入的數(shù)據(jù)不能為NULL。
一個(gè)表中只能由一列時(shí)主鍵,不能同時(shí)有多列是主鍵。設(shè)計(jì)表的時(shí)候,一般最好設(shè)定一個(gè)主鍵,常見(jiàn)的主鍵都是數(shù)字形式的。
自增主鍵auto_increment
在實(shí)際開(kāi)發(fā)中,往往有一系列的策略來(lái)保證主鍵不重復(fù),最常見(jiàn)的方法就是設(shè)置自增主鍵,系統(tǒng)可以自動(dòng)給數(shù)據(jù)分配,用戶也可以同時(shí)手動(dòng)進(jìn)行干預(yù),因?yàn)镸ySQL中內(nèi)置了自增主鍵功能,所以使用非常簡(jiǎn)單.
下圖中id這一列就變成了自增主鍵,用戶在插入數(shù)據(jù)時(shí),就可以不必手動(dòng)干預(yù)了.
Q:執(zhí)行以下操作,猜想該表的查詢結(jié)果是什么?
已知Id字段設(shè)置為自增主鍵.
張三的id = null,由于自增主鍵按照順序它的id = 1;李四的id = 1,主鍵不能重復(fù),李四的id和張三的id重復(fù),所以插入失敗;繼續(xù)插入李四數(shù)據(jù),此時(shí)設(shè)置id = 4,沒(méi)有和原有數(shù)據(jù)重復(fù),所以插入成功;王五的id = null,按照自增主鍵接著上一個(gè)順序往下走,所以它的id = 5;
那么我們來(lái)看一下結(jié)果:
5. foreign key
外鍵用于關(guān)聯(lián)其他表的主鍵,保證一個(gè)表中的數(shù)據(jù)匹配另一個(gè)表中的值的參照完整性。
foreign key (字段名) references 主表(列)
下面我們舉個(gè)例子來(lái)理解下,我們現(xiàn)在創(chuàng)建兩張表并想把它們關(guān)聯(lián)起來(lái),應(yīng)該如何操作呢?
首先思考一下這個(gè)對(duì)應(yīng)關(guān)系,一個(gè)學(xué)生對(duì)應(yīng)一個(gè)班級(jí),一個(gè)班級(jí)對(duì)應(yīng)多個(gè)學(xué)生.在學(xué)生表中id為主鍵,那我們可以設(shè)置學(xué)生class_id為外鍵,去關(guān)聯(lián)比班級(jí)表.
創(chuàng)建班級(jí)表class,設(shè)置classsId為主鍵
create table class ( id int primary key auto_increment, name varchar(20) );
創(chuàng)建學(xué)生表student,設(shè)置id為主鍵
create table student ( id int primary key auto_increment, name varchar(20), class_id int, foreign key (class_id) references class(id) );
MUL表示外鍵約束;
外鍵的使用規(guī)則
學(xué)生表中的插入的班級(jí)Id,必須在班級(jí)表中存在;
班級(jí)表是空的,這個(gè)時(shí)候插入學(xué)生表數(shù)據(jù)并給class_id = 1,而班級(jí)號(hào)在班級(jí)表中是空的,所以插入失敗.學(xué)生表指定的這個(gè)外鍵約束,必須是班級(jí)表的主鍵;外鍵約束建立好了以后,此時(shí)班級(jí)表中的班級(jí)id就不能再隨意修改或刪除;
我們無(wú)法將班級(jí)表中id = 1的記錄修改為id = 20,因?yàn)閷W(xué)生表中的張三依賴于班級(jí)表id = 1這樣的結(jié)果.
外鍵的缺點(diǎn)
加入假如我們有下面這樣一個(gè)商品-訂單關(guān)聯(lián)的兩張表
此時(shí)我們可以使用訂單表中的商品id和商品表中的商品id建立外鍵約束,但是當(dāng)訂單表中有了一個(gè)商品Id為1的記錄時(shí),就無(wú)法刪除商品表中的id = 1的記錄了,那么這個(gè)數(shù)據(jù)就會(huì)持久的存下去,但是商品不一定永久存在,很有可能就下架了,這就是外鍵在關(guān)聯(lián)某些表時(shí)的矛盾所在.
如果我們既希望擁有外鍵約束的校驗(yàn)功能,同時(shí)也希望可以解決當(dāng)前的矛盾,那么我們可以進(jìn)行邏輯刪除:給商品單獨(dú)添加一列,標(biāo)識(shí)數(shù)據(jù)是否有效,設(shè)定flag = 1表示記錄有效,flag = 0表示記錄無(wú)效.需要?jiǎng)h除的商品,可以直接把它的標(biāo)識(shí)改為0,邏輯上標(biāo)識(shí)已經(jīng)刪除了該商品,但實(shí)際上該數(shù)據(jù)還在表中存儲(chǔ),并不是真正意義上的物理刪除.
6. check
保證列中的值符合指定的條件。
總結(jié)
到此這篇關(guān)于MySQL中常見(jiàn)的六個(gè)約束類型的文章就介紹到這了,更多相關(guān)MySQL常見(jiàn)約束類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
win10下mysql 8.0.16 winx64安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了win10下mysql 8.0.16 winx64安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05Mysql使用函數(shù)json_extract處理Json類型數(shù)據(jù)的方法實(shí)例
在日常業(yè)務(wù)開(kāi)發(fā)中通常mysql數(shù)據(jù)庫(kù)中某個(gè)字段會(huì)需要存儲(chǔ)json格式字符串,下面這篇文章主要給大家介紹了關(guān)于Mysql使用函數(shù)json_extract處理Json類型數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-09-09MyBatis中實(shí)現(xiàn)動(dòng)態(tài)SQL標(biāo)簽
動(dòng)態(tài)SQL是MyBatis的一項(xiàng)強(qiáng)大功能,它允許開(kāi)發(fā)者根據(jù)條件動(dòng)態(tài)地生成SQL語(yǔ)句,本文主要介紹了MyBatis中實(shí)現(xiàn)動(dòng)態(tài)SQL標(biāo)簽,感興趣的可以可以了解一下2024-09-09Mysql分組排序取每組第一條的2種實(shí)現(xiàn)方式
開(kāi)發(fā)中經(jīng)常會(huì)遇到,分組查詢最新數(shù)據(jù)的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Mysql分組排序取每組第一條的2種實(shí)現(xiàn)方式,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02完美解決MySQL通過(guò)localhost無(wú)法連接數(shù)據(jù)庫(kù)的問(wèn)題
下面小編就為大家?guī)?lái)一篇完美解決MySQL通過(guò)localhost無(wú)法連接數(shù)據(jù)庫(kù)的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02教你如何恢復(fù)使用MEB備份的MySQL數(shù)據(jù)庫(kù)
這篇文章主要介紹了教你如何恢復(fù)使用MEB備份的MySQL數(shù)據(jù)庫(kù)的具體方法,需要的朋友可以參考下2016-09-09