## 约束
约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性、唯一性。
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)