@[toc]
MySQL約束概述
MySQL約束是一種限制,它通過限制表中的數(shù)據,來確保數(shù)據的完整性和唯一性。使用約束來限定表中的數(shù)據是很有必要的。
在 MySQL 中,約束是指對表中數(shù)據的一種約束,能夠幫助數(shù)據庫管理員更好地管理數(shù)據庫,并且能夠確保數(shù)據庫中數(shù)據的正確性和有效性。
- 例如,在數(shù)據表中存放年齡的值時,如果存入 200、300 這些無效的值就毫無意義了。因此,使用約束來限定表中的數(shù)據范圍是很有必要的。
在 MySQL 中,主要支持以下 6 種約束:
主鍵約束(PRIMARY KEY)
主鍵(PRIMARY KEY)的完整稱呼是“主鍵約束”,是 MySQL 中使用最為頻繁的約束。一般情況下,為了便于 DBMS 更快的查找到表中的記錄,都會在表中設置一個主鍵。主鍵是表的一個特殊字段,該字段能唯一標識該表中的每條信息。例如,學生信息表中的學號是唯一的。
主鍵分為單字段主鍵和多字段聯(lián)合主鍵,
使用主鍵應注意以下幾點:
- 每個表只能定義一個主鍵。
- 主鍵值必須唯一標識表中的每一行,且不能為 NULL,即表中不可能存在有相同主鍵值的兩行數(shù)據。這是唯一性原則。
- 一個字段名只能在聯(lián)合主鍵字段表中出現(xiàn)一次。
- 聯(lián)合主鍵不能包含不必要的多余字段。當把聯(lián)合主鍵的某一字段刪除后,如果剩下的字段構成的主鍵仍然滿足唯一性原則,那么這個聯(lián)合主鍵是不正確的。這是最小化原則。
在創(chuàng)建表時設置主鍵約束
在創(chuàng)建數(shù)據表時設置主鍵約束,既可以為表中的一個字段設置主鍵,也可以為表中多個字段設置聯(lián)合主鍵。但是不論使用哪種方法,在一個表中主鍵只能有一個。
設置單字段主鍵
在 CREATE TABLE 語句中,通過 PRIMARY KEY 關鍵字來指定主鍵。
在定義字段的同時指定主鍵,語法格式如下:
<字段名> <數(shù)據類型> PRIMARY KEY [默認值]
例子:在 test_db 數(shù)據庫中創(chuàng)建 tb_emp3 數(shù)據表,其主鍵為 id,SQL 語句和運行結果如下。
mysql> CREATE TABLE tb_emp3
-> (
-> id INT(11) PRIMARY KEY,
-> name VARCHAR(25),
-> deptId INT(11),
-> salary FLOAT
-> );
Query OK, 0 rows affected (0.37 sec)
mysql> DESC tb_emp3;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.14 sec)
或者是在定義完所有字段之后指定主鍵,語法格式如下:
[CONSTRAINT <約束名>] PRIMARY KEY [字段名]
例子:在 test_db 數(shù)據庫中創(chuàng)建 tb_emp4 數(shù)據表,其主鍵為 id,SQL 語句和運行結果如下。
mysql> CREATE TABLE tb_emp4
-> (
-> id INT(11),
-> name VARCHAR(25),
-> deptId INT(11),
-> salary FLOAT,
-> PRIMARY KEY(id)
-> );
Query OK, 0 rows affected (0.37 sec)
mysql> DESC tb_emp4;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(25) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.14 sec)
設置聯(lián)合主鍵
所謂的聯(lián)合主鍵,就是這個主鍵是由一張表中多個字段組成的。
- 比如,設置學生選課數(shù)據表時,使用學生編號做主鍵還是用課程編號做主鍵呢?如果用學生編號做主鍵,那么一個學生就只能選擇一門課程。如果用課程編號做主鍵,那么一門課程只能有一個學生來選。顯然,這兩種情況都是不符合實際情況的。
- 實際上設計學生選課表,要限定的是一個學生只能選擇同一課程一次。因此,學生編號和課程編號可以放在一起共同作為主鍵,這也就是聯(lián)合主鍵了。
主鍵由多個字段聯(lián)合組成,語法格式如下:
PRIMARY KEY [字段1,字段2,…,字段n]
注意:當主鍵是由多個字段組成時,不能直接在字段名后面聲明主鍵約束。
例子:創(chuàng)建數(shù)據表 tb_emp5,假設表中沒有主鍵 id,為了唯一確定一個員工,可以把 name、deptId 聯(lián)合起來作為主鍵,SQL 語句和運行結果如下。
mysql> CREATE TABLE tb_emp5
-> (
-> name VARCHAR(25),
-> deptId INT(11),
-> salary FLOAT,
-> PRIMARY KEY(id,deptId)
-> );
Query OK, 0 rows affected (0.37 sec)
mysql> DESC tb_emp5;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| name | varchar(25) | NO | PRI | NULL | |
| deptId | int(11) | NO | PRI | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.14 sec)
在修改表時添加主鍵約束
主鍵約束不僅可以在創(chuàng)建表的同時創(chuàng)建,也可以在修改表時添加。但是需要注意的是,設置成主鍵約束的字段中不允許有空值。
在修改數(shù)據表時添加主鍵約束的語法格式如下:
ALTER TABLE <數(shù)據表名> ADD PRIMARY KEY(<字段名>);
查看 tb_emp2 數(shù)據表的表結構,SQL 語句和運行結果如下所示。
mysql> DESC tb_emp2;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | varchar(30) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.14 sec)
例子:修改數(shù)據表 tb_emp2,將字段 id 設置為主鍵,SQL 語句和運行結果如下。
mysql> ALTER TABLE tb_emp2
-> ADD PRIMARY KEY(id);
Query OK, 0 rows affected (0.94 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> DESC tb_emp2;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(30) | YES | | NULL | |
| deptId | int(11) | YES | | NULL | |
| salary | float | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.12 sec)
通常,當在修改表時要設置表中某個字段的主鍵約束時,要確保設置成主鍵約束的字段中值不能夠有重復的,并且要保證是非空的。否則無法設置主鍵約束。
刪除主鍵約束
當一個表中不需要主鍵約束時,就需要從表中將其刪除。刪除主鍵約束的方法要比創(chuàng)建主鍵約束容易的多。
刪除主鍵約束的語法格式如下所示:
ALTER TABLE <數(shù)據表名> DROP PRIMARY KEY;
例子:刪除 tb_emp2 表中的主鍵約束,SQL 語句和運行結果如下。
mysql> ALTER TABLE tb_emp2
-> DROP PRIMARY KEY;
Query OK, 0 rows affected (0.94 sec)
Records: 0 Duplicates: 0 Warnings: 0
由于主鍵約束在一個表中只能有一個,因此不需要指定主鍵名就可以刪除一個表中的主鍵約束。
MySQL 主鍵自增長
在 MySQL 中,當主鍵定義為自增長后,這個主鍵的值就不再需要用戶輸入數(shù)據了,而由數(shù)據庫系統(tǒng)根據定義自動賦值。每增加一條記錄,主鍵會自動以相同的步長進行增長。
通過給字段添加 AUTO_INCREMENT 屬性來實現(xiàn)主鍵自增長。語法格式如下:
字段名 數(shù)據類型 AUTO_INCREMENT
- 默認情況下,AUTO_INCREMENT 的初始值是 1,每新增一條記錄,字段值自動加 1。
- 一個表中只能有一個字段使用 AUTO_INCREMENT 約束,且該字段必須有唯一索引,以避免序號重復(即為主鍵或主鍵的一部分)。
- AUTO_INCREMENT 約束的字段必須具備 NOT NULL 屬性。
- AUTO_INCREMENT 約束的字段只能是整數(shù)類型(TINYINT、SMALLINT、INT、BIGINT 等)。
- AUTO_INCREMENT 約束字段的最大值受該字段的數(shù)據類型約束,如果達到上限,AUTO_INCREMENT 就會失效。
注意:加上 AUTO_INCREMENT 約束條件后,字段中的每個值都是自動增加的。因此,這個字段不可能出現(xiàn)相同的值。通常情況下,AUTO_INCREMENT 都是作為 id 字段的約束條件,并且將 id 字段作為表的主鍵。
指定自增字段初始值
如果第一條記錄設置了該字段的初始值,那么新增加的記錄就從這個初始值開始自增。
- 例如,如果表中插入的第一條記錄的 id 值設置為 5,那么再插入記錄時,id 值就會從 5 開始往上增加。
外鍵約束
MySQL 外鍵約束(FOREIGN KEY)是表的一個特殊字段,經常與主鍵約束一起使用。對于兩個具有關聯(lián)關系的表而言,相關聯(lián)字段中主鍵所在的表就是主表(父表),外鍵所在的表就是從表(子表)。
外鍵用來建立主表與從表的關聯(lián)關系,為兩個表的數(shù)據建立連接,約束兩個表中數(shù)據的一致性和完整性。
- 比如,一個水果攤,只有蘋果、桃子、李子、西瓜等 4 種水果,那么,你來到水果攤要買水果就只能選擇蘋果、桃子、李子和西瓜,其它的水果不能購買的。
主表刪除某條記錄時,從表中與之對應的記錄也必須有相應的改變。一個表可以有一個或多個外鍵,外鍵可以為空值,若不為空值,則每一個外鍵的值必須等于主表中主鍵的某個值。
定義外鍵時,需要遵守下列規(guī)則:
- 主表必須已經存在于數(shù)據庫中,或者是當前正在創(chuàng)建的表。如果是后一種情況,則主表與從表是同一個表,這樣的表稱為自參照表,結構稱為自參照完整性。
- 必須為主表定義主鍵。
- 主鍵不能包含空值,但允許在外鍵中出現(xiàn)空值。也就是說,只要外鍵的每個非空值出現(xiàn)在指定的主鍵中,這個外鍵的內容就是正確的。
- 在主表的表名后面指定列名或列名的組合。這個列或列的組合必須是主表的主鍵或候選鍵。
- 外鍵中列的數(shù)目必須和主表的主鍵中列的數(shù)目相同。
- 外鍵中列的數(shù)據類型必須和主表主鍵中對應列的數(shù)據類型相同。
在創(chuàng)建表時設置外鍵約束
在 CREATE TABLE 語句中,通過 FOREIGN KEY 關鍵字來指定外鍵,具體的語法格式如下:
[CONSTRAINT <外鍵名>] FOREIGN KEY 字段名 [,字段名2,…]
REFERENCES <主表名> 主鍵列1 [,主鍵列2,…]
注意:從表的外鍵關聯(lián)的必須是主表的主鍵,且主鍵和外鍵的數(shù)據類型必須一致。例如,兩者都是 INT 類型,或者都是 CHAR 類型。如果不滿足這樣的要求,在創(chuàng)建從表時,就會出現(xiàn)“ERROR 1005(HY000): Can't create table”錯誤。
在修改表時添加外鍵約束
外鍵約束也可以在修改表時添加,但是添加外鍵約束的前提是:從表中外鍵列中的數(shù)據必須與主表中主鍵列中的數(shù)據一致或者是沒有數(shù)據。
在修改數(shù)據表時添加外鍵約束的語法格式如下:
ALTER TABLE <數(shù)據表名> ADD CONSTRAINT <外鍵名>
FOREIGN KEY(<列名>) REFERENCES <主表名> (<列名>);
注意:在為已經創(chuàng)建好的數(shù)據表添加外鍵約束時,要確保添加外鍵約束的列的值全部來源于主鍵列,并且外鍵列不能為空。
刪除外鍵約束
當一個表中不需要外鍵約束時,就需要從表中將其刪除。外鍵一旦刪除,就會解除主表和從表間的關聯(lián)關系。
刪除外鍵約束的語法格式如下所示:
ALTER TABLE <表名> DROP FOREIGN KEY <外鍵約束名>;
唯一約束
MySQL 唯一約束(Unique Key)是指所有記錄中字段的值不能重復出現(xiàn)。
- 例如,為 id 字段加上唯一性約束后,每條記錄的 id 值都是唯一的,不能出現(xiàn)重復的情況。如果其中一條記錄的 id 值為‘0001’,那么該表中就不能出現(xiàn)另一條記錄的 id 值也為‘0001’。
唯一約束與主鍵約束相似的是它們都可以確保列的唯一性。不同的是,唯一約束在一個表中可有多個,并且設置唯一約束的列允許有空值,但是只能有一個空值。而主鍵約束在一個表中只能有一個,且不允許有空值。比如,在用戶信息表中,為了避免表中用戶名重名,可以把用戶名設置為唯一約束。
在創(chuàng)建表時設置唯一約束
唯一約束可以在創(chuàng)建表時直接設置,通常設置在除了主鍵以外的其它列上。
在定義完列之后直接使用 UNIQUE 關鍵字指定唯一約束,語法格式如下:
<字段名> <數(shù)據類型> UNIQUE
在修改表時添加唯一約束
在修改表時添加唯一約束的語法格式為:
ALTER TABLE <數(shù)據表名> ADD CONSTRAINT <唯一約束名> UNIQUE(<列名>);
刪除唯一約束
在 MySQL 中刪除唯一約束的語法格式如下:
ALTER TABLE <表名> DROP INDEX <唯一約束名>;
檢查約束
MySQL 檢查約束(CHECK)是用來檢查數(shù)據表中字段值有效性的一種手段,可以通過 CREATE TABLE 或 ALTER TABLE 語句實現(xiàn)。設置檢查約束時要根據實際情況進行設置,這樣能夠減少無效數(shù)據的輸入。
- 例如,學生信息表中的年齡字段是沒有負數(shù)的,并且數(shù)值也是有限制的。如果是大學生,年齡一般應該在 18~30 歲之間。在設置字段的檢查約束時要根據實際情況進行設置,這樣能夠減少無效數(shù)據的輸入。
選取設置檢查約束的字段
檢查約束使用 CHECK 關鍵字,具體的語法格式如下:
CHECK <表達式>
其中,“表達式”指的就是 SQL 表達式,用于指定需要檢查的限定條件。
若將 CHECK 約束子句置于表中某個列的定義之后,則這種約束也稱為基于列的 CHECK 約束。
在更新表數(shù)據的時候,系統(tǒng)會檢查更新后的數(shù)據行是否滿足 CHECK 約束中的限定條件。MySQL 可以使用簡單的表達式來實現(xiàn) CHECK 約束,也允許使用復雜的表達式作為限定條件,例如在限定條件中加入子查詢。
注意:若將 CHECK 約束子句置于所有列的定義以及主鍵約束和外鍵定義之后,則這種約束也稱為基于表的 CHECK 約束。該約束可以同時對表中多個列設置限定條件。
在創(chuàng)建表時設置檢查約束
一般情況下,如果系統(tǒng)的表結構已經設計完成,那么在創(chuàng)建表時就可以為字段設置檢查約束了。
創(chuàng)建表時設置檢查約束的語法格式如下:
CHECK(<檢查約束>)
在修改表時添加檢查約束
如果一個表創(chuàng)建完成,可以通過修改表的方式為表添加檢查約束。
修改表時設置檢查約束的語法格式如下:
ALTER TABLE tb_emp7 ADD CONSTRAINT <檢查約束名> CHECK(<檢查約束>)
刪除檢查約束
修改表時刪除檢查約束的語法格式如下:
ALTER TABLE <數(shù)據表名> DROP CONSTRAINT <檢查約束名>;
非空約束
MySQL 非空約束(NOT NULL)指字段的值不能為空。對于使用了非空約束的字段,如果用戶在添加數(shù)據時沒有指定值,數(shù)據庫系統(tǒng)就會報錯??梢酝ㄟ^ CREATE TABLE 或 ALTER TABLE 語句實現(xiàn)。在表中某個列的定義后加上關鍵字 NOT NULL 作為限定詞,來約束該列的取值不能為空。
- 比如,在用戶信息表中,如果不添加用戶名,那么這條用戶信息就是無效的,這時就可以為用戶名字段設置非空約束。
在創(chuàng)建表時設置非空約束
創(chuàng)建表時可以使用 NOT NULL 關鍵字設置非空約束,具體的語法格式如下:
<字段名> <數(shù)據類型> NOT NULL;
在修改表時添加非空約束
如果在創(chuàng)建表時忘記了為字段設置非空約束,也可以通過修改表進行非空約束的添加。
修改表時設置非空約束的語法格式如下:
ALTER TABLE <數(shù)據表名>
CHANGE COLUMN <字段名>
<字段名> <數(shù)據類型> NOT NULL;
刪除非空約束
修改表時刪除非空約束的語法規(guī)則如下:
ALTER TABLE <數(shù)據表名>
CHANGE COLUMN <字段名> <字段名> <數(shù)據類型> NULL;
默認值約束
默認值(Default)的完整稱呼是“默認值約束(Default Constraint)”,用來指定某列的默認值。在表中插入一條新記錄時,如果沒有為某個字段賦值,系統(tǒng)就會自動為這個字段插入默認值。
- 例如,員工信息表中,部門位置在北京的較多,那么部門位置就可以默認為“北京”,系統(tǒng)就會自動為這個字段賦值為“北京”。
默認值約束通常用在已經設置了非空約束的列,這樣能夠防止數(shù)據表在錄入數(shù)據時出現(xiàn)錯誤。
在創(chuàng)建表時設置默認值約束
創(chuàng)建表時可以使用 DEFAULT 關鍵字設置默認值約束,具體的語法格式如下:
<字段名> <數(shù)據類型> DEFAULT <默認值>;
其中,“默認值”為該字段設置的默認值,如果是字符類型的,要用單引號括起來。
注意:在創(chuàng)建表時為列添加默認值,可以一次為多個列添加默認值,需要注意不同列的數(shù)據類型。
在修改表時添加默認值約束
修改表時添加默認值約束的語法格式如下:
ALTER TABLE <數(shù)據表名>
CHANGE COLUMN <字段名> <數(shù)據類型> DEFAULT <默認值>;
刪除默認值約束
當一個表中的列不需要設置默認值時,就需要從表中將其刪除。
修改表時刪除默認值約束的語法格式如下:
ALTER TABLE <數(shù)據表名>
CHANGE COLUMN <字段名> <字段名> <數(shù)據類型> DEFAULT NULL;
MySQL查看表中的約束
在 MySQL 中可以使用 SHOW CREATE TABLE 語句來查看表中的約束。
查看數(shù)據表中的約束語法格式如下:
SHOW CREATE TABLE <數(shù)據表名>;