📚 目录
- [1. 什么是数据库约束?](#1. 什么是数据库约束?)
- [1.1 数据库约束类型的介绍](#1.1 数据库约束类型的介绍)
- [2. 数据库约束实操](#2. 数据库约束实操)
- [2.1 字段级约束:not null / default / unique / check](#2.1 字段级约束:not null / default / unique / check)
- [2.2 表级约束:primary key 主键](#2.2 表级约束:primary key 主键)
- [2.3 关联约束:foreign key 外键](#2.3 关联约束:foreign key 外键)
前言:
数据完整性是数据库设计的核心目标,MySQL 通过约束机制限制字段输入规范,规避空值、重复、非法数值、无效关联等脏数据。
本文会分类讲解六大基础约束,区分字段级、表级、外键关联约束,附完整建表示例,从概念到实操一步步讲解,适合零基础同学系统学习,也可作为开发速查笔记。
1. 什么是数据库约束?

想必大家都见过牵绳遛狗的场景:牵引绳就相当于一种约束,限制狗狗随意乱跑、避免伤人,规范它的活动范围。
** 数据库约束是用于保证数据完整性和一致性的一组规则,它强制数据必须遵守特定条件,否则数据库操作会被拒绝。**
1.1 数据库约束类型的介绍
六大基础约束主要分为三部分:子段级,表级,外键关联约束
| 类型 | 说明 |
|---|---|
| not null 非空约束 | 指定非空约束的列不能存储 null 值 |
| default 默认约束 | 当没有给列赋值时使用的默认值 |
| unique 唯一约束 | 指定唯一约束的列每行数据必须有唯一的值 |
| primary key 主键约束 | not null 和 unique 的结合,可以指定一个列或多个列,有助于防止数据重复和提高数据的查询性能 |
| foreign key 外键约束 | 外键约束是一种关系约束,用于定义两个表之间的关联关系,可以确保数据的完整性和一致性 |
| check 约束 | 用于限制列或数据在数据库表中的值,确保数据的准确性和可靠性 |
[🔙 返回目录](#🔙 返回目录)
2. 数据库约束实操
2.1 字段级约束:not null / default / unique / check
字段级约束not null:
作用:限制某字段不能为空,插入/更新该字段必须传入有效值,不允许为null;
sql
create table if not exists test (
id int not null,
name varchar(20)
);
我们可以使用desc来查看表结构:
sql
desc test;

我们可以看见: id列null位置的值为:NO ;此时就代表我们插入的元素不能为null,否则会报错;
sql
insert into test(id,name) values (1,'张三');
insert into test (name) values('王五');
insert into test values(null,'王五');
结果:

从执行结果可以看出,只有第一条 insert 语句成功执行。
字段级约束default:
** 作用:插入数据时若不给该字段传值,自动填充预设默认值;**
sql
create table if not exists test (
id int,
name varchar(20) default '匿名'
);
表结构:

也就是说,当我们没有指定当前列进行插入的时候,会自动帮我们插入默认值;
例如:
sql
-- 插入
insert into test(id) values (1);
-- 查询
select* from test;
当我们没有指定列进行插入的时候,会采取默认值;

字段级约束 unique:
** 作用:当前字段所有行数据不能重复,允许存入多个 null。**
sql
create table if not exists test (
id int unique,
name varchar(20)
);
insert into test(id,name) values (1,'张三');
insert into test(id,name) values (2,'王五');
具体表结构:

此时插入的数据都能够成功进行插入,当我们再插入id为1的值的时候,就会报错:
sql
insert into test(id,name) values (1,'李四');

字段级约束check:
** 作用:自定义字段取值范围,不符合条件的数据直接拦截。**
sql
create table if not exists test (
id int check(id<10 and id > 5),
name varchar(20)
);
表结构:

插入数据:
sql
insert into test(id,name) values (6,'张三');
insert into test(id,name) values (7,'王五');
insert into test(id,name) values (8,'李四');
此时插入:这三条数据都是符合要求的数据,当我们插入不符合要求的数据,就会报错:
sql
insert into test(id,name) values (1,'李四');
insert into test(id,name) values (11,'李四');

[🔙 返回目录](#🔙 返回目录)
2.2 表级约束:primary key 主键
主键约束等价于 not null + unique,一张表只能有一个主键,分为单字段主键 与复合多字段主键 ,同时主键会自动生成索引,大幅提升查询速度。
方式1: 字段后面直接声明;
sql
create table user(
id int primary key comment '用户主键id',
username varchar(20) not null
);
方式2: 表末尾统一声明(支持复合主键)
sql
create table user_role(
user_id int,
role_id int,
-- 复合主键,user_id + role_id 组合唯一
primary key(user_id, role_id)
);
注意:
1. 主键字段不能为 null,整表唯一;
2. 一张表仅允许存在一组 primary key;
3. 推荐使用自增 int 类型作为业务主键。
自增主键:auto_increment
当我们没有指定主键列进行插入数据的时候,数据库会自动根据表中最大值进行插入:
例如:
sql
insert into user_role (username) values ('张三');

此时我们可以知道:自增主键是从1开始的;
sql
insert into user_role (username) values ('张三');
insert into user_role values (100,'张三');
insert into user_role (username) values ('张三');
结果:

自增主键是在最大值的基础上进行相加1的;
我们也可以进行修改自增主键增加的位置:
修改自增主键
- 表必须是 auto_increment 自增主键;
- 新起始值必须大于当前表已存在最大主键 id;
- 若表内已有数据,不能设置比现有最大 id 更小的值。
方法一:
sql
alter table 表名 auto_increment = 目标起始值;
方法二:
sql
truncate table 表名;
注意:
-
truncate(清空所有数据,自增直接重置为 1)并且数据不可恢复 -
外键关联场景下,子表不能直接 truncate,需先解除外键 / 删除子表数据 -
delete 删除数据不会重置自增方法三: 表内数据已存在,想把自增改小(只能删数据重建)
MySQL 不支持将自增起点修改为小于当前已存在最大主键的数值,若业务需要缩小自增起点,只能先删除对应 id 区间的数据,再执行 alter table 修改。
[🔙 返回目录](#🔙 返回目录)
2.3 关联约束:foreign key 外键
** 作用: 外键用来维护两张表的参照完整性,子表字段必须匹配主表主键,防止出现无关联的脏数据;仅 InnoDB 引擎支持外键,MyISAM 不生效**
sql
create table if not exists class (
class_id int primary key auto_increment,
name varchar(20)
);
create table if not exists student (
student_id int primary key auto_increment,
name varchar(20) not null,
class_id int,
foreign key(class_id) references class(class_id)
);
核心规则:
- 插入学生数据时,class_id 必须是 class 表里已存在的班级编号,否则插入失败;
- 不能直接删除还有学生关联的班级数据,数据库会拦截删除操作;
- 外键字段 class_id 和关联主键 class_id 的数据类型必须完全一致;
- 进阶扩展:可追加 on update cascade、on delete cascade 实现级联更新 / 删除
例如:
我们先向:class中添加几个数据:
sql
insert into class(name) values
('一班'),
('二班'),
('三班');
执行后 class_id 会自增生成 1、2、3。
sql
insert into student(name, class_id) values
('张三', 1),
('李四', 1),
('王五', 2),
('赵六', 3);
此时我们是能成功进行 插入的;
当我们插入不在class中存在的数据时:数据库会报错;
sql
insert into student(name, class_id) values('小明', 99);

- 执行顺序强制要求:有外键关联时,先创建主表,后创建子表,如果先执行 student 表建表语句,此时class表不存在,MySQL 会直接创建失败,student 表不会生成,后续执行 insert 语句会报Unknown column 'class_id'字段不存在错误。
- 字段类型匹配:外键字段class_id和关联主键class_id数据类型必须完全一致(本例均为 int)。
- 存储引擎限制:只有innodb引擎支持外键,myisam 引擎外键不会生效,无法校验关联数据。
- 约束效果:插入、更新学生时,class_id必须是 class 表中已存在的主键值;无法直接删除存在关联学生的班级数据。
[🔙 返回目录](#🔙 返回目录)