MySQL數(shù)據(jù)庫表的約束詳解析
約束是為了安全插入數(shù)據(jù),保證數(shù)據(jù)的合法性,防止無效數(shù)據(jù)進(jìn)入數(shù)據(jù)庫。它類似編譯器語法提示,減少防止程序員在不知情的情況下插入錯(cuò)誤數(shù)據(jù)。其中數(shù)據(jù)類型本身就是一種約束。
表的約束:表中一定要有各種約束,通過約束讓我們未來插入數(shù)據(jù)庫表中的數(shù)據(jù)是否合法的預(yù)期。本質(zhì)通過技術(shù)手段倒逼程序員插入正確的數(shù)據(jù)。而站在MySQL視角,插入進(jìn)來是數(shù)據(jù)一定是合法的。
為什么要約束:數(shù)據(jù)庫是維護(hù)數(shù)據(jù)的最后一道防線,必須保證數(shù)據(jù)的完整性和可預(yù)期性。
1.null屬性
在建表過程中,我們?yōu)閿?shù)據(jù)類型添加時(shí)可以指定null或not null屬性。
- null:表示在插入數(shù)據(jù)時(shí)這一列可以為空,如果不顯示添加任何屬性,默認(rèn)就為null。
- not null:表示在插入數(shù)據(jù)時(shí)該列必須填寫。
如下:
- 對于null屬性的數(shù)據(jù),在填寫時(shí)可以不對該列填寫,默認(rèn)為null。
- 對于not null屬性的數(shù)據(jù),在填寫時(shí)不可忽略。
如下:
這樣對于必須填寫數(shù)據(jù)的列就可以對空值進(jìn)行攔截。
2.默認(rèn)值約束(default)
在建表時(shí)可以對類型設(shè)置默認(rèn)值屬性,如果進(jìn)行顯示填寫,會(huì)被默認(rèn)設(shè)置為null。默認(rèn)值可以是null,或者一個(gè)確切的值,比如‘男’,‘張三’,20254063等。
測試:
當(dāng)我們進(jìn)行插入數(shù)據(jù)時(shí),不對某些向插入也是可行的,它會(huì)自動(dòng)帶上默認(rèn)值。
mysql> insert into test2 (name) values('張三'); Query OK, 1 row affected (0.01 sec) mysql> select*from test2; +------+--------+--------+ | id | gender | name | +------+--------+--------+ | 0 | 男 | 張三 | +------+--------+--------+ 1 row in set (0.00 sec) mysql>
not null屬性和default屬性可以同時(shí)設(shè)置。它們并不沖突,而是一種互補(bǔ)功能。帶有not null屬性列也可以選擇不插入,讓它選擇默認(rèn)值,但前提必須是default屬性不為null。
mysql> create table test3( -> id int default 0 not null, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.01 sec) mysql> insert into test3 (name) values('李四'); Query OK, 1 row affected (0.01 sec) mysql> insert into test3 (id) values(2025302); ERROR 1364 (HY000): Field 'name' doesn't have a default value mysql>
not null作用在用戶插入的時(shí)候。default作用在用戶忽略這一列的時(shí)候。一般情況下設(shè)置not null,不會(huì)帶default。
3.comment
comment屬性是列描述,更像是一種注釋,給程序員看的。可以理解為軟約束。
如下:
mysql> create table test4( -> id int comment '用戶編號', -> name varchar(20) comment '用戶名' -> ); Query OK, 0 rows affected (0.02 sec) mysql> show create table test4; +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | test4 | CREATE TABLE `test4` ( `id` int(11) DEFAULT NULL COMMENT '用戶編號', `name` varchar(20) DEFAULT NULL COMMENT '用戶名' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql>
4.zerofill
zerofill是 MySQL 中用于數(shù)值類型(如 INT, SMALLINT, BIGINT 等)的一個(gè)約束,它的主要作用是在顯示數(shù)值時(shí)用前導(dǎo)零填充,以達(dá)到指定的字段寬度。
比如在創(chuàng)建數(shù)值類型時(shí)int(4),其中的4,表示時(shí)最小寬度為4位,如果加了zerofill屬性,則不足4位的在前面添上0。
mysql> create table test5( -> a int(4) zerofill, -> b int(4) -> ); Query OK, 0 rows affected (0.02 sec) mysql> insert into test5 values(231,231); Query OK, 1 row affected (0.00 sec) mysql> select*from test5; +------+------+ | a | b | +------+------+ | 0231 | 231 | +------+------+ 1 row in set (0.00 sec) mysql>
當(dāng)我們不指明對齊長度時(shí),對于int類型默認(rèn)為11,int unsigned類型默認(rèn)為10。因?yàn)閕nt類型和int unsigned類型最大值分別是四十多億和二十多億。都是10位數(shù)字,而對于int類型還需要有負(fù)號所以為11位。
應(yīng)用場景:
- 產(chǎn)品編號:如 "00123" 而不是 "123"
- 會(huì)員卡號:如 "0000000456"
- 訂單編號:保持固定位數(shù)便于人工核對
5.主鍵(primary key)
主鍵:primary key用來唯一的約束該字段里面的數(shù)據(jù),不能重復(fù),不能為空,一張表中最多只能有一個(gè)主鍵。主鍵所在的列通常是整數(shù)類型。
在數(shù)據(jù)庫操作中,增刪查改通常需要依賴主鍵,以確保數(shù)據(jù)的唯一性和操作的準(zhǔn)確性。
在插入數(shù)據(jù)時(shí)不允許主鍵重復(fù)。
mysql> create table test_key( -> id int primary key, -> name varchar(20) -> ); Query OK, 0 rows affected (0.02 sec) mysql> insert into test_key values(2025401,'張三'); Query OK, 1 row affected (0.00 sec) mysql> insert into test_key values(2025401,'李四'); ERROR 1062 (23000): Duplicate entry '2025401' for key 'PRIMARY' mysql> insert into test_key values(2025402,'李四'); Query OK, 1 row affected (0.00 sec) mysql> insert into test_key values(2025403,'李四'); Query OK, 1 row affected (0.01 sec) mysql> select*from test_key; +---------+--------+ | id | name | +---------+--------+ | 2025401 | 張三 | | 2025402 | 李四 | | 2025403 | 李四 | +---------+--------+ 3 rows in set (0.00 sec) mysql>
建表后才想起來加主鍵時(shí),要保證沒有重復(fù)數(shù)據(jù)。
只能有一個(gè)主鍵不意味著一個(gè)表中的主鍵只能添加給一列??梢栽O(shè)給多列,稱為復(fù)合主鍵。
現(xiàn)在只有id和course_id同時(shí)和歷史數(shù)據(jù)重復(fù)時(shí)才不被允許插入。如上也就是不能讓學(xué)生的學(xué)號和選擇的課重復(fù)記錄。
id和course兩者合起來才是一個(gè)主鍵。
6.自增長(auto_increment)
自增長屬性主要作用于主鍵,主鍵有時(shí)候只是單純的表示數(shù)據(jù)的唯一性,并不表示一種復(fù)雜的信息。此時(shí)可以把它設(shè)為自增長。也就是主鍵的信息不用我們自己去維護(hù)(插入),而是我們插入數(shù)據(jù)時(shí)會(huì)給該行自動(dòng)添加主鍵信息。
要實(shí)現(xiàn)主鍵自增長添屬性auto_increment即可。
mysql> create table test7( -> id int primary key auto_increment, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.02 sec) mysql> insert into test7 (name) values('李華'); Query OK, 1 row affected (0.01 sec) mysql> select*from test7; +----+--------+ | id | name | +----+--------+ | 1 | 李華 | +----+--------+ 1 row in set (0.00 sec) mysql>
如上我們并不需要手動(dòng)輸入id,系統(tǒng)會(huì)幫我們自動(dòng)填充。 當(dāng)然我們也可以手動(dòng)插入。
我們再對自增長進(jìn)行深入理解,觀察下面插入結(jié)果。
mysql> insert into test7 (name) values('張三'); Query OK, 1 row affected (0.00 sec) mysql> insert into test7 (id,name) values(50,'李四'); Query OK, 1 row affected (0.00 sec) mysql> insert into test7 (name) values('王五'); Query OK, 1 row affected (0.00 sec) mysql> select*from test7; +----+--------+ | id | name | +----+--------+ | 1 | 李華 | | 2 | 張三 | | 50 | 李四 | | 51 | 王五 | +----+--------+ 4 rows in set (0.00 sec) mysql>
可以發(fā)現(xiàn)當(dāng)我們插入50后下一次自動(dòng)從51開始自增。其實(shí)在表結(jié)構(gòu)中存在auto_increment參數(shù)會(huì)記錄次序。在建表時(shí)如果不進(jìn)行設(shè)置auto_increment默認(rèn)為1,也就是在下一次插入時(shí),主鍵默認(rèn)值為1。當(dāng)我們手動(dòng)插入50后,auto_increment變成51,從51自增。如下查看表的創(chuàng)建屬性:
比如我們要給2026屆的大一新生進(jìn)行編號,可以把a(bǔ)uto_increment參數(shù)設(shè)為20260001,即:
mysql> create table student( -> id int primary key auto_increment, -> name varchar(20) not null -> )auto_increment=20260001; Query OK, 0 rows affected (0.01 sec)
7.唯一鍵(unique)
一張表中有往往有很多字段需要唯一性,數(shù)據(jù)不能重復(fù),但是一張表中只能有一個(gè)主鍵,剩下需要唯一性約束的字段就可以使用唯一鍵。
唯一鍵的本質(zhì)和主鍵差不多,唯一鍵允許為空,而且可以多個(gè)為空,空字段不做唯一性比較。
關(guān)于唯一鍵和主鍵的區(qū)別:我們可以簡單理解成,主鍵更多的是標(biāo)識(shí)唯一性的。而唯一鍵更多的是保證在業(yè)務(wù)上,不要和別的信息出現(xiàn)重復(fù)。最好把主鍵設(shè)計(jì)成為和當(dāng)前業(yè)務(wù)無關(guān)的字段,這樣,當(dāng)業(yè)務(wù)調(diào)整的時(shí)候,我們可以盡量不會(huì)對主鍵做過大的調(diào)整。
唯一鍵和主鍵并不沖突而是互補(bǔ)的。
mysql> create table stu( -> id int primary key auto_increment, -> telephone char(11) unique, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.01 sec) mysql> insert into stu values(20250302,18756623304,'張三'); Query OK, 1 row affected (0.01 sec) mysql> insert into stu values(20250305,18756623304,'李四'); ERROR 1062 (23000): Duplicate entry '18756623304' for key 'telephone' mysql> insert into stu values(20250307,null,'王五'); Query OK, 1 row affected (0.00 sec) mysql>
8.外鍵
外鍵約束的是表和表之間的關(guān)系。比如兩個(gè)表:一個(gè)稱為主表,一個(gè)稱為從表。外鍵約束主要定義在從表上,主表則必須是有主鍵約束或unique約束。當(dāng)定義外鍵后,要求外鍵列數(shù)據(jù)必須在主表的主鍵列存在或?yàn)閚ull。
比如一個(gè)學(xué)生表和班級表的關(guān)系。
- 主表:班級表
- 從表:學(xué)生表
對于學(xué)生表,在clase_id這一列必須依賴于班級表中的id這一列,學(xué)生不能填一個(gè)不存在的班級。對于班級表,如果該班級下還有學(xué)生不能把該班的id改變或刪除。
語法:在從表的列項(xiàng)中加 語法:foreign key (字段名) references 主表(列)
注意:因?yàn)橥怄I是在從表上建立,需要主表的信息,所以需要先建主表。
如下:
mysql> create table class( -> id int primary key, -> name varchar(20) not null -> ); Query OK, 0 rows affected (0.02 sec) mysql> create table students( -> id int primary key, -> name varchar(20) not null, -> class_id int, -> foreign key(class_id) references class(id) -> ); Query OK, 0 rows affected (0.01 sec) mysql>
Query OK, 0 rows affected (0.01 sec) mysql> insert into class values(1,'經(jīng)濟(jì)統(tǒng)計(jì)'); Query OK, 1 row affected (0.00 sec) mysql> insert into class values(2,'網(wǎng)絡(luò)安全'); Query OK, 1 row affected (0.00 sec) mysql> insert into class values(3,'機(jī)電工程'); Query OK, 1 row affected (0.00 sec) mysql> insert into students values(2025023,'張三',1); Query OK, 1 row affected (0.00 sec) mysql> insert into students values(2025024,'李四',5); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`constraintTest`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)) mysql> delete from class where id=3; Query OK, 1 row affected (0.00 sec) mysql> delete from class where id=1; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`constraintTest`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)) mysql>
到此這篇關(guān)于MySQL數(shù)據(jù)庫表的約束的文章就介紹到這了,更多相關(guān)mysql數(shù)據(jù)庫表約束內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中動(dòng)態(tài)生成SQL語句去掉所有字段的空格的操作方法
在數(shù)據(jù)庫管理過程中,我們常常會(huì)遇到需要對表中字段進(jìn)行清洗和整理的情況,本文將詳細(xì)介紹如何在MySQL中動(dòng)態(tài)生成SQL語句來去掉所有字段的空格,感興趣的朋友一起看看吧2025-04-04淺談sql語句中GROUP BY 和 HAVING的使用方法
GROUP BY語句和HAVING語句,經(jīng)過研究和練習(xí),終于明白如何使用了,在此記錄一下同時(shí)添加了一個(gè)自己舉的小例子,通過寫這篇文章來加深下自己學(xué)習(xí)的效果,還能和大家分享下,同時(shí)也方便以后查閱,一舉多得,下面由小編來和大家一起學(xué)習(xí)2019-05-05解析mysqldump的delay-insert選項(xiàng)
本篇文章是對mysqldump的delay-insert選項(xiàng)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06MySQL日期時(shí)間類型與字符串互相轉(zhuǎn)換的方法
這篇文章主要介紹了MySQL日期時(shí)間類型與字符串互相轉(zhuǎn)換的方法,文中通過代碼示例和圖文結(jié)合的方式給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-07-07詳解MySQL與Spring的自動(dòng)提交(autocommit)
這篇文章主要介紹了MySQL與Spring的自動(dòng)提交(autocommit)的的相關(guān)資料,幫助大家更好的理解和使用MySQL與spring,感興趣的朋友可以了解下2021-01-01MySQL數(shù)據(jù)庫之內(nèi)置函數(shù)和自定義函數(shù) function
這篇文章主要介紹了MySQL數(shù)據(jù)庫之內(nèi)置函數(shù)和自定義函數(shù) function,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-06-06