深入淺析MySQL中常見的6種約束類型

深入淺析MySQL中常見的6種約束類型

約束的字面意思就是規定或者限制某個事該如何去做,在mysql中,約束就是對數據表中數據指定規則,也就是對數據進行限制,以此來確保可靠性,比如不允許某列出現Null值,實際中我們會遇到以下類型的約束。

  • NOT NULL?: 確保列不能有NULL值
  • CHECK?: 確保列中的值滿足特定條件
  • UNIQUE?: 確保一列中的所有值都不同
  • PRIMARY KEY: NOT NULL和UNIQUE組合,唯一標識表中的每一行
  • FOREIGN KEY?: 外鍵約束
  • DEFAULT?: 如果未指定值,則為列設置默認值

【相關推薦:mysql視頻教程

約束

1.NULL

MySQL中通過使用NOT NULL確保列中不會出現Null值,創建表時候格式如下:

mysql>?create?table?user(name?varchar(255)not?null); Query?OK,?0?rows?affected?(0.06?sec)

如果試圖插入一個null值,則會拋出異常。

mysql>?insert?user?values(null); ERROR?1048?(23000):?Column?'name'?cannot?be?null

或者在現有表上新增NOT NULL約束。

mysql>?alter?table?user?modify?name?varchar(255)?not?null; Query?OK,?0?rows?affected?(0.07?sec) Records:?0??Duplicates:?0??Warnings:?0

刪除NOT NULL約束。

mysql>?alter?table?user?modify?name?varchar(255)??null; Query?OK,?0?rows?affected?(0.09?sec) Records:?0??Duplicates:?0??Warnings:?0

2.CHECK

如果想在列上定義條件約束,可以使用CHECK,比如下面,強制讓年齡字段大于18,小于80,否則將會報錯。

mysql&gt;?create?table?user(age?int(11)?check(age&gt;18?and?age?<p>插入測試,可以發現9、81在插入的時候拋出異常。</p><pre class="brush:js;toolbar:false;">mysql&gt;?insert?user?values(9); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated.  mysql&gt;?insert?user?values(19); Query?OK,?1?row?affected?(0.01?sec)  mysql&gt;?insert?user?values(81); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;

也可以進行多列約束,如年齡必須大于18,城市必須為中國。

mysql&gt;?create?table?user(age?int(11),city?varchar(255)?,check(age&gt;18?and?city='中國')); Query?OK,?0?rows?affected,?1?warning?(0.05?sec)

插入測試。

mysql&gt;?insert?user?values(81,'2'); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;?insert?user?values(8,'2'); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;?insert?user?values(20,'2'); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;?insert?user?values(20,'中國'); Query?OK,?1?row?affected?(0.01?sec)  mysql&gt;?insert?user?values(20,'中國1'); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;?insert?user?values(85,'中國'); Query?OK,?1?row?affected?(0.01?sec)  mysql&gt;?insert?user?values(9,'中國'); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated.

還可以讓列值必須在指定集合中,如性別必須在男、女、未知、人妖集合中。

mysql&gt;?create?table?user(sex?varchar(255)?check?(sex?in?('男','女','未知','人妖'))); Query?OK,?0?rows?affected?(0.05?sec)

插入測試。

mysql&gt;?insert?user?values("男"); Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?insert?user?values("男男"); ERROR?3819?(HY000):?Check?constraint?'user_chk_1'?is?violated. mysql&gt;?insert?user?values("女"); Query?OK,?1?row?affected?(0.01?sec)  mysql&gt;?insert?user?values("人妖"); Query?OK,?1?row?affected?(0.00?sec)

為約束命名并刪除約束。

mysql&gt;?create?table?user?(age?int(11)?,constraint?CHK_AGE?check(age&gt;18)); Query?OK,?0?rows?affected,?1?warning?(0.05?sec)  mysql&gt;?insert?user?values(5); ERROR?3819?(HY000):?Check?constraint?'CHK_AGE'?is?violated.  mysql&gt;?alter?table?user?drop?check?CHK_AGE; Query?OK,?0?rows?affected?(0.03?sec) Records:?0??Duplicates:?0??Warnings:?0mysql&gt;?insert?user?values(5); Query?OK,?1?row?affected?(0.01?sec)

但是,這樣的寫法你見過嗎?

猜猜下面的作用是什么。

這其實是一個case when條件判斷,讓其僅僅可以插入>=18,或者是在0-10之間的數。

CREATE?TABLE?`user`?(`age`?int(11)?CHECK? (((case?when?(`age`?&gt;=18)?then?1? else? (case?when?age0?then?1?else?2?end)?end)?=1)));

3.UNIQUE

UNIQUE約束確保列中的沒有重復的值,UNIQUE和?PRIMARY KEY約束都為一列值的唯一性提供保障,但是UNIQUE每個表可以出現多次,而PRIMARY KEY只能出現一個。

如下面name字段不能重復。

mysql&gt;?create?table?user?(name?varchar(255),unique(name)); Query?OK,?0?rows?affected?(0.07?sec)

插入測試。

mysql&gt;?insert?user?values("張三"); Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?insert?user?values("張三"); ERROR?1062?(23000):?Duplicate?entry?'張三'?for?key?'user.name'mysql&gt;

對此約束進行起名,并刪除。

mysql&gt;?create?table?user?(name?varchar(255),constraint?name_un?unique(name)); Query?OK,?0?rows?affected?(0.07?sec)  mysql&gt;?insert?user?values("張三"); Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?insert?user?values("張三"); ERROR?1062?(23000):?Duplicate?entry?'張三'?for?key?'user.name_un' mysql&gt;?alter?table?user?drop?index?name_un; Query?OK,?0?rows?affected?(0.03?sec) Records:?0??Duplicates:?0??Warnings:?0  mysql&gt;?insert?user?values("張三"); Query?OK,?1?row?affected?(0.02?sec)

插入后可以用以下語句查看創建語句。

mysql&gt;?show?create?table?user; +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ |?Table?|?Create?Table?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????| +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ |?user??|?CREATE?TABLE?`user`?( ??`name`?varchar(255)?DEFAULT?NULL, ??UNIQUE?KEY?`name_un`?(`name`) )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8mb4?COLLATE=utf8mb4_0900_ai_ci?| +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1?row?in?set?(0.00?sec)

要刪除UNIQUE約束,可以使用DROP INDEX或ALTER TABLE語句:

mysql&gt;?DROP?INDEX?name_un?ON?user; Query?OK,?0?rows?affected?(0.03?sec) Records:?0??Duplicates:?0??Warnings:?0  mysql&gt;?show?create?table?user; +-------+-----------------------------------------------------------------------------------------------------------------------------+ |?Table?|?Create?Table????????????????????????????????????????????????????????????????????????????????????????????????????????????????| +-------+-----------------------------------------------------------------------------------------------------------------------------+ |?user??|?CREATE?TABLE?`user`?( ??`name`?varchar(255)?DEFAULT?NULL )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8mb4?COLLATE=utf8mb4_0900_ai_ci?| +-------+-----------------------------------------------------------------------------------------------------------------------------+ 1?row?in?set?(0.00?sec)

在現有表上添加。

mysql&gt;?alter?table?user?add?constraint?name_un?unique(name); Query?OK,?0?rows?affected?(0.04?sec) Records:?0??Duplicates:?0??Warnings:?0

4.PRIMARY KEY

通常每個表中包含一個用于唯一標識每一行的值,這個列就被稱為PRIMARY KEY。

mysql&gt;?create?table?user?(id?int(11)?,age?int(11),primary?key?(id)); Query?OK,?0?rows?affected,?2?warnings?(0.06?sec)  mysql&gt;?insert?user?values(1,2); Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?insert?user?values(1,2); ERROR?1062?(23000):?Duplicate?entry?'1'?for?key?'user.PRIMARY'mysql&gt;

5.FOREIGN KEY

FOREIGN KEY用于約束表中的一個字段必須是另一個表中某個字段所存在的值,但是在另一個表中,這個列不一定是主鍵,但必須是唯一性索引,否則會創建失敗。

比如orders表中的userId必須參考user表中的id,如果插入的userId在user表中不存在,則無法插入。

mysql&gt;?create?table?orders?(id?int(11)?primary?key?,userId?int(11)?,??FOREIGN?KEY?(userId)?REFERENCES?user(id)?); Query?OK,?0?rows?affected,?2?warnings?(0.06?sec)  mysql&gt;?insert?orders?values(1,3); ERROR?1452?(23000):?Cannot?add?or?update?a?child?row:?a?foreign?key?constraint?fails?(`t`.`orders`,?CONSTRAINT?`orders_ibfk_1`?FOREIGN?KEY?(`userId`)?REFERENCES?`user`?(`id`))  mysql&gt;?insert?orders?values(1,1); Query?OK,?1?row?affected?(0.01?sec)

但是存在一個問題,如果主表(user)中記錄被刪除或者更新,那orders中的記錄該怎么辦?,如下面的例子,可以發現直接報錯了。

mysql&gt;?update?user?set?id?=2?where?id?=1;  Cannot?delete?or?update?a?parent?row:?a?foreign?key?constraint?fails?(`t`.`orders`,?CONSTRAINT?`orders_ibfk_1`?FOREIGN?KEY?(`userId`)?REFERENCES?`user`?(`id`)

MySQL提供了幾個約束可以幫助我們解決這類問題,比如在user表更新時,orders也相繼更新。

  1. RESTRICT:如果子表中有記錄,則拒絕更新或刪除父表中的記錄。

  2. CASCADE:更新或刪除父表中的記錄時,自動更新或刪除子表中的記錄。

  3. SET NULL:在更新或刪除父表記錄時,將子表中字段的值設置為空。

可以發現,默認采用的是RESTRICT,下面來修改一下,讓在更新時候也同樣更新,在刪除時候設置null。

mysql&gt;?alter?table?orders?add?constraint?orders_ibfk_1??FOREIGN?KEY?(`userId`)?REFERENCES?`user`?(`id`)?on?update?cascade?on delete?set?null; Query?OK,?0?rows?affected?(0.12?sec) Records:?0??Duplicates:?0??Warnings:?0

測試更新

mysql&gt;?select?*?from?user; +----+--------+ |?id?|?name???| +----+--------+ |??1?|?張三???| +----+--------+ 1?row?in?set?(0.00?sec)  mysql&gt;?select?*?from?orders; Empty?set?(0.00?sec)  mysql&gt;?insert?orders?values?(1,1); Query?OK,?1?row?affected?(0.01?sec)  mysql&gt;?update?user?set?id?=2?where?id?=1; Query?OK,?1?row?affected?(0.01?sec) Rows?matched:?1??Changed:?1??Warnings:?0  mysql&gt;?select?*?from?orders; +----+--------+ |?id?|?userId?| +----+--------+ |??1?|??????2?| +----+--------+ 1?row?in?set?(0.01?sec)

測試刪除。

mysql&gt;?delete?from?user?where?id?=2; Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?select?*?from?orders; +----+--------+ |?id?|?userId?| +----+--------+ |??1?|???NULL?| +----+--------+ 1?row?in?set?(0.00?sec)

6.DEFAULT

DEFAULT約束用于為列設置默認值,如果沒有為某個字段賦值,系統就會自動為這個字段插入默認值,沒有賦值指的是在insert插入數據時沒有指明這個字段,如果指定null值,最終存放的還是null值。

mysql&gt;?create?table?user(age?int(11)?default?18); Query?OK,?0?rows?affected,?1?warning?(0.05?sec)  mysql&gt;?insert?user?values(); Query?OK,?1?row?affected?(0.02?sec)  mysql&gt;?select?*?from?user; +------+ |?age??| +------+ |???18?| +------+ 1?row?in?set?(0.00?sec)

原文地址:https://juejin.cn/post/7000352993572814885作者:i聽風逝夜

更多編程相關知識,請訪問:mysql視頻教程!!

? 版權聲明
THE END
喜歡就支持一下吧
點贊12 分享