一、概念
数据库约束是作用于表中字段上的规则,用于限制存储在表中的数据。使用约束可以保证数据库中数据的正确、有效和完整。我们可以在创建表或修改表的时候在表字段上添加约束。
常见的约束类型如下图所示:
约束类型  | 关键字  | 描述  | 
非空约束  | NOT NULL  | 限制该字段的数据不能为null  | 
唯一约束  | UNIQUE  | 保证该字段的数据是唯一的、不可重复的  | 
主键约束  | PRIMARY KEY  | 主键是一行数据的唯一标识,要求非空且唯一  | 
默认约束  | DEFAULT  | 保存数据时,如果没有指定该字段的值,则采用默认值  | 
检查约束  | CHECK  | 插入数据值根据指定条件校验数据的合法性  | 
外键约束  | FORENGN KEY  | 用来让两张表的数据之间建立连接,保证数据的完整性和一致性  | 
我们可以把约束分为两类,普通约束和外键约束。普通约束包含主键约束、非空约束、唯一约束、检查约束、默认约束。
二、普通约束
1.建表时添加约束
我们在建表时可以添加主键约束、非空约束、默认约束、检查约束、唯一约束等。
CREATE TABLE t_user (
	id BIGINT PRIMARY KEY auto_increment NOT NULL,
	name VARCHAR ( 50 ) NOT NULL UNIQUE,
	age INT CHECK ( age > 0 && age <= 150 ),
status CHAR ( 1 ) DEFAULT '1' 
) ENGINE = INNODB主键ID使用了主键约束和非空约束、name使用了非空约束和唯一约束、age使用了检查约束、status使用了默认约束。
注意:
- 当我们使用
check约束时,约束条件必须写在()中。 - 当我们使用
default约束指定默认值时,默认值必须符合字段数据类型。 - 每个表只能为一个字段指定主键
PRIMARY KEY约束。 - 在一些正常情况下,可以在一个字段上使用多个约束条件。
 
2.建表后再添加约束的情况
a.添加主键约束
语法:
alter table 表名 add primary key(表字段名);SQL语句:
ALTER TABLE t_user ADD PRIMARY KEY ( id );b.添加唯一约束
语法:
ALTER TABLE 表名 add UNIQUE(表字段名);SQL语句:
ALTER TABLE t_user ADD UNIQUE (name)c.添加默认约束
语法:
ALTER TABLE 表名 modify 表字段名 数据类型 default 默认值;SQL语句:
ALTER TABLE t_user MODIFY status CHAR ( 1 ) DEFAULT '1';d.添加非空约束
语法:
ALTER TABLE 表名 modify 表字段名 数据类型 not null;SQL语句:
ALTER TABLE t_user modify name varchar(50) not null;e.添加检查约束
语法:
ALTER TABLE 表名 add CONSTRAINT 表字段名 check(检查条件);SQL语句:
ALTER TABLE t_user ADD CONSTRAINT age CHECK (age > 0 & age <= 150)三、外键约束
如果两张表存在某种联系,比如一张表中的某个字段需要依赖于另外一张表,这两个表就存在关联关系,外键约束用于互相约束彼此的行为,从而保证数据的一致性和完整性。
特别说明:
- 添加外键时必须得确保需要关联的父表已经创建
 - 一个表可存在多个外键,且可以关联多个表
 
我们首先创建一个父表
CREATE TABLE t_department (
id BIGINT PRIMARY KEY auto_increment,
name VARCHAR ( 50 ) NOT NULL COMMENT '部门名称')1.建表时添加外键约束
语法:
CREATE TABLE 表名(
字段名    数据类型,
...
[CONSTRAINT] [外键名称]  FOREIGN  KEY (子表字段名)   REFERENCES   父表 (父表字段名)
);SQL语句:
CREATE TABLE t_employee (
	id BIGINT PRIMARY KEY auto_increment,
	name VARCHAR ( 50 ) NOT NULL UNIQUE COMMENT '职工名称',
dept_id BIGINT COMMENT '所属部门',
CONSTRAINT fk_dept_id FOREIGN KEY ( dept_id ) REFERENCES t_department ( id ))执行完SQL语句之后我们查看t_staff数据表,发现已经成功添加了外键信息。

2.建表后添加外键约束
语法:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (子表字段名) REFERENCES 父表 (父表字段名);我们先删除之间建表时添加的外键约束。

SQL语句:
ALTER TABLE t_employee ADD CONSTRAINT fk_dept FOREIGN KEY ( dept_id ) REFERENCES t_department ( id );我们执行SQL语句发现我们的外键约束信息再次被添加成功了。

3.外键测试
我们在测试之前先添加一些测试数据。

子表添加外键约束后,默认情况使用的约束行为是RESTRICT,这种行为下我们无法直接删除父表中的数据,必须先删除所有子表中关联该父表记录的数据才能删除父表的数据。

这种情况,我们需要先删除子表的所有关联数据之后,才能删除父表的数据。


4.外键删除
语法:
ALTER TABLE  表名   DROP  FOREIGN  KEY  外键名称;SQL语句:
ALTER TABLE t_employee DROP FOREIGN KEY fk_dept;5.更新、删除行为
常见的外键约束行为如下图所示:
行为  | 说明  | 
NO ACTION  | 当在父表中更新、删除数据时,首先检查该数据是否有对应的外键,如果有则不允许更新、删除。  | 
RESTRICT  | 和NO ACTION的行为一致(默认)  | 
CASCADE  | 当在父表中更新、删除数据时,首先检查该数据是否有对应的外键,如果有则会更新、删除子表中的相关数据  | 
SET NULL  | 当在父表中更新、删除数据时,首先检查该数据是否有对应的外键,如果有则设置子表中该外键值为null  | 
SET DEFAULT  | 父表有变更时,子表将外键列设置成一个默认的值(InnoDB存储引擎不支持)  | 
语法:
ALTER TABLE  表名  ADD CONSTRAINT  外键名称  FOREIGN KEY  (外键字段)   REFERENCES
父表名 (父表字段名)  ON UPDATE [更新行为] ON DELETE [删除行为]SQL语句:
CASCADE测试:
ALTER TABLE t_employee ADD CONSTRAINT fk_dept FOREIGN KEY ( dept_id ) REFERENCES t_department ( id ) ON UPDATE CASCADE ON DELETE CASCADE;
我们知道cascade是删除父表中的记录,如果子表中存在关联的数据那么也会同时删除子表中关联的数据。
测试数据如下所示:

我们执行删除父表中的数据
delete from t_department WHERE id=1;我们刷新数据,发现子表中对应的父表记录也被删除掉了。

RESTRICT和NO ACTION的测试:
这两个我们前面已经测试过了,要删除父表中的数据,必须是先删除子表中的数据或者子表没有对应的数据才可以。
SET NULL测试:
我们把外键的约束行为修改成set null
alter table t_employee add CONSTRAINT fk_dept foreign key(dept_id) REFERENCES t_department(id) on UPDATE set null on delete set null;我们的测试数据如下所示:

我们再次执行删除父表的数据
delete from t_department WHERE id=1;执行SQL语句之后,我们刷新数据发现父表中的数据已经被删除了,子表对应的数据被设置成null











