约束
约 1573 字大约 5 分钟
2025-07-28
4.1 概述
约束是作用于表字段上的规则,用于限制表中存储的数据,以保证数据的完整性和准确性。主要有以下几种类型的约束:
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为 null 。 | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复的。 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一。 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值。 | DEFAULT |
检查约束 | 保证字段值满足某一个条件(8.0.16 版本之后)。 | CHECK |
外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性。 | FOREIGN KEY |
4.2 约束演示
下面将通过一个案例来演示如何在创建表、修改表时指定约束。
案例需求: 根据需求,完成表结构的创建。需求如下:
字段名 | 字段含义 | 字段类型 | 约束条件 | 约束关键字 |
---|---|---|---|---|
id | ID 唯一标识 | int | 主键,并且自动增长 | PRIMARY KEY, AUTO_INCREMENT |
name | 姓名 | varchar(10) | 不为空,并且唯一 | NOT NULL UNIQUE |
age | 年龄 | int | 大于 0,并且小于等于 120 | CHECK |
status | 状态 | char(1) | 如果没有指定该值,默认为 1 | DEFAULT |
gender | 性别 | char(1) | 无 |
对应的建表语句为:
CREATE TABLE tb_user(
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID 唯一标识',
name VARCHAR(10) NOT NULL UNIQUE COMMENT '姓名',
age INT CHECK (age > 0 && age <= 120) COMMENT '年龄',
status CHAR(1) DEFAULT '1' COMMENT '状态',
gender CHAR(1) COMMENT '性别'
);
在 CREATE TABLE
语句中,可以在字段定义后直接添加约束关键字来为字段添加约束。
可以通过以下 SQL 语句插入数据进行测试:
insert into tb_user(name,age,status,gender) values ('Toml',19,'1','男'),
('Tom2',25,'0','男');
insert into tb_user(name,age,status,gender) values ('Tom3',19,'1','男');
insert into tb_user (name, age, status,gender) values (null, 19, '1','男');
insert into tb_user(name,age,status,gender) values ('Tom3',19,'1','男');
insert into tb_user (name,age,status,gender) values ('Tom4',80,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom5',-1,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom5',121,'1','男');
insert into tb_user (name, age, gender) values ('Tom5',120,'男');
以上 SQL 语句用于向 tb_user
表中插入不同的数据,以此来测试之前定义的约束是否生效,例如,插入 name
为 null
的数据,或者 age
不在 0
到 120
之间的数据,观察数据库是否会报错,从而验证 NOT NULL
约束和 CHECK
约束是否生效。
4.3 外键约束
4.3.1 介绍
外键约束用于在两张表之间建立连接,保证数据的一致性和完整性。通过外键,可以确保子表中的数据必须与父表中的数据相关联。
为了更好地理解外键约束,我们首先准备两张表:dept
(部门表) 和 emp
(员工表)。
首先,创建 dept
表:
create table dept(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '部门名称'
)comment '部门表';
INSERT INTO dept (id, name) VALUES (1, '研发部'), (2, '市场部'),(3,'财务部'), (4,
'销售部'), (5, '总经办');
然后创建 emp
表:
create table emp (
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '姓名',
age int comment '年龄',
job varchar(20) comment '职位',
salary int comment '薪资',
entrydate date comment '入职时间',
managerid int comment '直属领导ID',
dept_id int comment '部门ID'
) comment '员工表';
INSERT INTO emp (id, name, age, job, salary, entrydate, managerid, dept_id)
VALUES
(1, '金庸', 66, '总裁',20000, '2000-01-01', null, 5), (2, '张无忌', 20,
'项目经理',12500, '2005-12-05', 1,1),
(3, '杨逍', 33, '开发', 8400, '2000-11-03', 2,1),(4, '韦一笑', 48,'开
发',11000, '2002-02-05', 2,1),
(5,'常遇春', 43, '开发',10500, '2004-09-07', 3,1), (6, '小昭',19,'程序员鼓励师',6600, '2004-10-12', 2,1);
在没有外键约束的情况下,如果删除了 dept
表中 id
为 1
的部门,emp
表中 dept_id
为 1
的员工数据就会变得无效,破坏了数据的完整性。
因此,需要使用外键约束来避免这种情况的发生。
4.3.2 语法
建表时添加外键:
CREATE TABLE 表名(
字段名 数据类型,
...
[CONSTRAINT] [外键名称] FOREIGN KEY (外键字段名) REFERENCES 主表(主表列名)
);
为表添加外键约束:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表(主表列名);
案例
为 emp
表的 dept_id
字段添加外键约束,关联 dept
表的主键 id
。
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept (id);
添加了外键约束之后,再到 dept
表(父表)删除 id
为 1
的记录,此时将会报错,不能删除或更新父表记录,因为存在外键约束。
4.3.3 删除/更新行为
当父表中的数据被删除或更新时,外键约束会触发相应的行为,以保证数据的一致性。这些行为被称为删除 / 更新行为。具体的删除 / 更新行为有以下几种:
行为 | 说明 |
---|---|
NO ACTION | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 RESTRICT 一致) 默认行为 |
RESTRICT | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 NO ACTION 一致) |
CASCADE | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。 |
SET NULL | 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为 null (这就要求该外键允许取 null )。 |
SET DEFAULT | 父表有变更时,子表将外键列设置成一个默认的值 (Innodb 不支持) |
具体语法为:
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名) REFERENCES 主表名(主表字段名)
ON UPDATE CASCADE ON DELETE CASCADE;
使用 ON UPDATE CASCADE ON DELETE CASCADE
,可以实现父表数据更新或删除时,子表中的关联数据也自动更新或删除,从而维护数据的一致性。