1.1 什么是約束
約束字面意思就是限制,比如我們每一個(gè)人的身份證號(hào)都是唯一的,不可能出現(xiàn)兩個(gè)人,身份證是一樣的,那么這里的唯一性我們就稱之為一種約束,再比如:我們每個(gè)人都是有性別的,或男或女或其他,不可能出現(xiàn)一個(gè)人他沒(méi)有性別,那么這里的不能為空同樣也是一種約束。在數(shù)據(jù)庫(kù)中也有很多約束,數(shù)據(jù)庫(kù)的數(shù)據(jù)必須要滿足約束才可正確插入,否則就會(huì)報(bào)錯(cuò),下面我們具體學(xué)習(xí)約束的內(nèi)容
1.2主鍵約束
1.2.1 主鍵約束
主鍵約束(PRIMARY KEY),簡(jiǎn)稱主鍵,該約束的作用是定義一個(gè)主鍵來(lái)唯一確定表中每一行數(shù)據(jù)的標(biāo)識(shí)符,我們把它拆解開(kāi)來(lái)說(shuō):
- 使用了主鍵的字段的值,必須是唯一的,不能重復(fù)
- 主鍵的列,不能包含NULL值
- 每個(gè)表最多只能有一個(gè)主鍵。
1.2.2 添加主鍵約束
創(chuàng)建表時(shí),聲明主鍵,示例代碼如下:
CREATE TABLE People(
id int PRIMARY KEY,
name VARCHAR(30),
age INT
);
創(chuàng)建完成后,我們看一下People表的表結(jié)構(gòu),如下:
MySQL> desc People;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(30) | YES | | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql>
這里我們發(fā)現(xiàn)id字段在NULL列的值為NO,在KEY列有個(gè)PRI鍵,這個(gè)就表示該字段為主鍵,下面我們?cè)囈幌拢绻覀儾迦霐?shù)據(jù)時(shí),主鍵字段為空,報(bào)什么錯(cuò),報(bào)錯(cuò)如下:
mysql> insert into People(id,name,age) values(NULL,"張三",'20');
ERROR 1048 (23000): Column 'id' cannot be null
mysql>
從上面的報(bào)錯(cuò)我們可以看出主鍵不能為空,為空就會(huì)報(bào)上面的錯(cuò),下面我們?cè)賮?lái)驗(yàn)證一下主鍵id字段不能重復(fù),代碼如下:
mysql> insert into People(id,name,age) values(1,"張三",'20');
Query OK, 1 row affected (0.01 sec)
mysql> insert into People(id,name,age) values(1,"張三",'20');
ERROR 1062 (23000): Duplicate entry '1' for key 'people.PRIMARY'
mysql>
我們最開(kāi)始插入了一條數(shù)據(jù),然后我們又插入了一遍,發(fā)現(xiàn)報(bào)錯(cuò)了,提示id的值重復(fù)了,主鍵是不能重復(fù)的。
1.2.3 聯(lián)合主鍵
我們上面的主鍵為id,即只需要一個(gè)字段就可以標(biāo)識(shí)數(shù)據(jù)的唯一性,有的時(shí)候我們的表需要兩個(gè)及以上的字段組合起來(lái),才能確定一條記錄的唯一性,舉個(gè)例子,假如我們要設(shè)計(jì)一張統(tǒng)計(jì)一個(gè)地區(qū)學(xué)生信息的表,一個(gè)地區(qū)有多個(gè)學(xué)校,每個(gè)學(xué)校都有自己的編號(hào),而每個(gè)學(xué)校的學(xué)生有自己的學(xué)校,當(dāng)我們想要確定這個(gè)地區(qū)的某個(gè)學(xué)生時(shí)候,單單使用學(xué)號(hào)是無(wú)法確定的,因?yàn)橛卸鄠€(gè)學(xué)校,學(xué)號(hào)肯定有重復(fù)的,此時(shí)我們就需要學(xué)校和學(xué)生學(xué)號(hào)兩個(gè)字段才能準(zhǔn)確確定一個(gè)學(xué)生,這個(gè)時(shí)候就需要將這兩個(gè)字段設(shè)置成聯(lián)合主鍵。聯(lián)合主鍵還是一個(gè)主鍵,只不過(guò)這個(gè)主鍵是由多個(gè)字段共同確定的。
示例代碼如下:
CREATE TABLE AreaStuInfo(
sch_no INT,
stu_no INT,
name VARCHAR(30),
CONSTRAINT pk_sch_stu_id PRIMARY KEY (sch_no,stu_no)
);
這個(gè)時(shí)候,我們?cè)俨樵円幌卤斫Y(jié)構(gòu),結(jié)果如下:
mysql> DESC AreaStuInfo;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| sch_no | int | NO | PRI | NULL | |
| stu_no | int | NO | PRI | NULL | |
| name | varchar(30) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
從上面的結(jié)果我們發(fā)現(xiàn),sch_no和stu_no兩個(gè)字段的KEY列的值都有PRI,也就意味著sch_no和stu_no兩者的值一樣,就會(huì)觸發(fā)約束,報(bào)錯(cuò),但是如果僅僅是這兩個(gè)列的某一個(gè)列的值一樣,它是不會(huì)報(bào)錯(cuò)。
1.2.4 刪除主鍵約束
當(dāng)我們不需要主鍵約束的時(shí)候,我們可使用如下的代碼,將某一張的主鍵刪除,語(yǔ)法如下:
ALTER TABLE 表名 DROP PRIMARY KEY;
示例代碼如下:
mysql> DESC AreaStuInfo;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| sch_no | int | NO | PRI | NULL | |
| stu_no | int | NO | PRI | NULL | |
| name | varchar(30) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> ALTER TABLE AreaStuInfo DROP PRIMARY KEY;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC AreaStuInfo;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| sch_no | int | NO | | NULL | |
| stu_no | int | NO | | NULL | |
| name | varchar(30) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql>
1.2.5 自動(dòng)增長(zhǎng)列
我們有的時(shí)候,希望表的某一個(gè)字段的值是自動(dòng)增長(zhǎng)的,比如編號(hào),從1開(kāi)始,依次+1,在數(shù)據(jù)庫(kù)中,我們可以使用auto_increment自動(dòng)增長(zhǎng)列關(guān)鍵字來(lái)實(shí)現(xiàn),數(shù)據(jù)庫(kù)會(huì)自動(dòng)生成該字段的值默認(rèn)開(kāi)始的值是1,我們也可以修改起始值,語(yǔ)法如下:
ALTER TABLE 表名 AUTO_INCREMENT=值
此外值得注意的是,如果一個(gè)字段是自動(dòng)增長(zhǎng)的列,那么該字段的數(shù)據(jù)類型必須是整型且必須是主鍵,下面我們看一個(gè)示例:
CREATE TABLE `People` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`age` int DEFAULT NULL
);
我們看一下表結(jié)構(gòu):
mysql> desc People;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
我們有自動(dòng)增長(zhǎng)列的表中插入數(shù)據(jù)的時(shí)候,可以不為id字段設(shè)置值,也可以為其設(shè)置成null,示例代碼如下:
mysql> insert into People(name,age) values("王二",20);
Query OK, 1 row affected (0.01 sec)
mysql> insert into People(id,name,age) values(Null,"李四",20);
Query OK, 1 row affected (0.00 sec)
mysql> select * from People;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 王二 | 20 |
| 2 | 李四 | 20 |
+----+--------+------+
2 rows in set (0.00 sec)
mysql>
從上面的示例上我們可以看出,我們即使沒(méi)有指定id字段的值,也是不會(huì)報(bào)錯(cuò)的,數(shù)據(jù)庫(kù)會(huì)自動(dòng)為其生成值。
1.3 非空約束
所謂非空的約束,其實(shí)很簡(jiǎn)單,如果那個(gè)字段的值添加了非空的約束,那么這個(gè)字段的值就不能為NULL,如果是NULL,就會(huì)報(bào)錯(cuò),示例代碼如下:
mysql> desc People;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| age | int | YES | | NULL | |
| sex | char(30) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> insert into People(name,age,sex) values('張三',29,NULL);
ERROR 1048 (23000): Column 'sex' cannot be null
mysql>
我們從通過(guò)查詢People的表結(jié)構(gòu)發(fā)現(xiàn),sex字段不能為空,當(dāng)我們?cè)诓迦霐?shù)據(jù)的時(shí)候,如果把該字段插入一個(gè)空值,那么就會(huì)報(bào)錯(cuò)。添加非空約束的語(yǔ)法如下,只需要在需要添加的字段后面,增加NOT NULL即可。示例代碼如下:
CREATE TABLE `People` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`age` int DEFAULT NULL,
`sex` CHAR(30) NOT NULL
);
1.4 唯一約束
唯一約束也很簡(jiǎn)單,就是字面意思,如果一個(gè)字段被添加了唯一約束,那么該字段的值就只能是唯一的,不可重復(fù)的,添加唯一約束方式也很簡(jiǎn)單,直接在數(shù)據(jù)類型的后面加上UNIQUE關(guān)鍵字即可,示例代碼如下:
CREATE TABLE `Person` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(30) UNIQUE,
`age` int
);
以我們這里的Person表為例,所有數(shù)據(jù)的名字都不能重復(fù),如果重復(fù)則會(huì)報(bào)錯(cuò),示例如下:
mysql> desc person;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | UNI | NULL | |
| age | int | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> insert into person(name,age) values("張三",20);
Query OK, 1 row affected (0.00 sec)
mysql> insert into person(name,age) values("張三",20);
ERROR 1062 (23000): Duplicate entry '張三' for key 'person.name'
mysql>
但是這個(gè)唯一約束對(duì)一個(gè)值例外,就是NULL,在MySQL中,NULL與任意一個(gè)值都不相等,連和它自己都不相等,多以如果名稱這一列有多條記錄,但是它的值是空的,也是不會(huì)報(bào)錯(cuò)的。
1.5 結(jié)尾
本期的內(nèi)容就到這里了,如有不足之處還請(qǐng)大家多多指正,歡迎大家留言、關(guān)注、轉(zhuǎn)發(fā)、收藏,謝謝。






