## 約束
約束是一種限制,它通過對表的行或列的數據做出限制,來確保表的數據的完整性、唯一性。
MYSQL 中常用的幾種約束:
| 約束類型 | 主鍵 | 默認值 | 唯一 | 外鍵 | 非空 |
| --- | --- | --- | --- | --- | --- |
| 關鍵字 | PRIMARY KEY | DEFAULT | UNIQUE | FOREIGN KEY | NOT NULL |
### 主鍵(PRIMARY KEY)
用于約束表中的一行,作為這一行的標識符。主鍵要求這一行的數據不能有重復且不能為空。
還有一種特殊的主鍵:復合主鍵。主鍵不僅可以是表中的一列,也可以由表中的兩列或多列來共同標識。
### 默認值(DEFAULT)
規定當有 DEFAULT 約束的列,插入數據時沒有值該怎么辦。
DEFAULT 約束只會在插入數據時體現出來,如果被 DEFAULT 約束的位置沒有值,那么這個位置將會被 DEFAULT 的值填充。
### 唯一(UNIQUE)
它規定一張表中指定的一列的值必須不能有重復值,即這一列每個值都是唯一的。
當新插入的數據和已有數據重復的時候,如果有 UNIQUE 約束,則插入失敗。
### 外鍵(FOREIGN KEY)
既能確保數據完整性,也能表現表之間的關系。
一個表可以有多個外鍵,每個外鍵必須參考(REFERENCES)另一個表的主鍵,被外鍵約束的列,取值必須在它參考的列中有對應值。
添加外鍵語法:
ALTER TABLE table_name
ADD [CONSTRAINT constraint_name] FOREIGN KEY [index_name] (index_col_name, ...)
REFERENCES table_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
alter table `user` add foreign key fk_group_id (group_id) references `group` (id) on update cascade on delete cascade;
模式介紹:
- CASCADE: 在父表上 update/delete 記錄時,同步 update/delete 掉子表的匹配記錄。
- NO ACTION: 如果子表中有匹配的記錄,則不允許對父表對應候選鍵進行 update/delete 操作。
- RESTRICT: (默認模式) 同 NO ACTION, 都是立即檢查外鍵約束。
- SET NULL: 在父表上 update/delete 記錄時,將子表上匹配記錄的列設為 NULL,**注意:** 子表的外鍵列不能為 NOT NULL
外鍵約束使用最多的兩種情況:
(1)父表更新時子表也更新,父表刪除時如果子表有匹配的項,刪除失敗;
(2)父表更新時子表也更新,父表刪除時子表匹配的項也刪除。
前一種情況:在外鍵定義中,我們使用 ON UPDATE CASCADE ON DELETE RESTRICT;
后一種情況:在外鍵定義中,可以使用 ON UPDATE CASCADE ON DELETE CASCADE;
刪除外鍵語法:
ALTER TABLE table_name DROP FOREIGN KEY fk_symbol;
### 非空約束(NOT NULL)
聽名字就能理解,被非空約束的列,在插入值時必須非空。
在 MySQL 中違反非空約束,不會報錯,只會有警告。
### 外鍵示例
```
// 創建測試表
CREATE DATABASE IF NOT EXISTS koogua_test;
USE koogua_test;
CREATE TABLE IF NOT EXISTS category(
cat_id int not null auto_increment primary key,
cat_name varchar(30) not null
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS product(
prd_id int not null auto_increment primary key,
prd_name varchar(100) not null,
cat_id int not null,
key cat_id(cat_id)
)ENGINE=InnoDB;
ALTER TABLE product ADD CONSTRAINT fk_prd_category
FOREIGN KEY (cat_id)
REFERENCES category(cat_id)
ON UPDATE CASCADE
ON DELETE RESTRICT;
// 插入測試數據
INSERT INTO category VALUES (null, '電腦');
INSERT INTO category VALUES (null, '手機');
INSERT INTO product VALUES (null, '電腦001', 1);
INSERT INTO product VALUES (null, '電腦002', 1);
INSERT INTO product VALUES (null, '手機001', 2);
INSERT INTO product VALUES (null, '手機002', 2);
// 更新分類編號,產品表的分類編號也跟著改變了
UPDATE category SET cat_id = 11 WHERE cat_id = 1;
// 刪除分類,產品表中有相關記錄,拒絕刪除
DELETE FROM category WHERE cat_id = 2;
// 插入不存在的分類編號
INSERT INTO product VALUES (null, '手機099', 99);
```
參考鏈接:
- [MySQL外鍵](http://www.studymysql.com/mysql/foreign-key.html)
- [Using FOREIGN KEY Constraints](https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html)