在 SQL 中,约束(Constraint)是用于限制表中数据的规则,目的是保证数据的完整性、一致性和有效性。常见的约束类型包括:主键约束、外键约束、非空约束、唯一约束、检查约束、默认值约束等。下面结合你提供的代码,详细讲解这些约束及其应用。
一、SQL 中常见的约束类型
主键约束(PRIMARY KEY)
- 作用:唯一标识表中的每条记录,确保记录的唯一性。
- 特点:一个表只能有一个主键;主键列的值不能重复(唯一),且不能为
NULL
;通常与auto_increment
(自增)配合使用,自动生成唯一值。
非空约束(NOT NULL)
- 作用:限制列的值不能为
NULL
,必须提供具体数据。 - 特点:如果插入数据时未指定该列的值,会报错。
- 作用:限制列的值不能为
唯一约束(UNIQUE)
- 作用:确保列中的所有值都是唯一的(不重复)。
- 特点:与主键的区别是,一个表可以有多个唯一约束;唯一约束允许列值为
NULL
(且可以有多个NULL
,因为NULL
不等于任何值)。
检查约束(CHECK)
- 作用:限制列的值必须满足指定的条件(如范围、格式等)。
- 特点:确保数据符合业务规则,例如年龄必须在 0-120 之间。
默认值约束(DEFAULT)
- 作用:当插入数据时未指定该列的值,自动使用默认值。
外键约束(FOREIGN KEY)
- 作用:建立两个表之间的关联关系(父子表),确保子表中引用的外键值在主表的主键中存在(或为
NULL
),维护数据的参照完整性。 - 相关概念:
- 主表(父表):被引用的表(如
dept
表)。 - 子表(从表):引用主表的表(如
emp
表)。 - 外键列:子表中用于关联主表主键的列(如
emp.dept_id
关联dept.id
)。
- 主表(父表):被引用的表(如
- 级联操作(通过
ON UPDATE
和ON DELETE
指定):CASCADE
:当主表的主键更新 / 删除时,子表的外键值同步更新 / 删除。SET NULL
:当主表的主键更新 / 删除时,子表的外键值设为NULL
(需确保外键列允许NULL
)。
- 作用:建立两个表之间的关联关系(父子表),确保子表中引用的外键值在主表的主键中存在(或为
二、代码详解
以下是对提供的 SQL 代码的逐段解释:
1. 创建user
表
create table user(id int primary key auto_increment comment '主键', -- 主键约束+自增name varchar(10) not null unique comment '姓名', -- 非空约束+唯一约束age int check (age >= 0 and age <= 120) comment '年龄', -- 检查约束status char(1) default '1' comment '状态', -- 默认值约束gender char(1) comment '性别' -- 无特殊约束
)comment '用户表';
id
:主键(primary key
),确保每条用户记录唯一;auto_increment
表示插入时无需手动指定,自动递增生成。name
:not null
(必须提供姓名)+unique
(姓名不能重复)。age
:check
约束限制年龄必须在 0-120 之间(若插入年龄为 150,会报错)。status
:default '1'
表示若插入时未指定status
,默认值为 '1'(可理解为 “正常” 状态)。
2. 插入数据到user
表
-- 插入3条完整数据
insert into user(name, age, status, gender) values
('Tom1', 19, '0', '男'),
('Tom2', 25, '1', '女'),
('Tom3', 17, '0', '男');-- 插入时未指定status,会使用默认值'1'
insert into user(name, age, gender) values ('Tom5', 32,'男');
- 第一条插入语句显式指定了所有列的值,
status
分别为 '0'、'1'、'0'。 - 第二条插入语句未指定
status
,因此status
会自动使用默认值 '1'。
3. 创建dept
表(部门表)
create table dept(id int primary key auto_increment comment 'ID' , -- 主键+自增name varchar(50) not null comment '部门名称' -- 非空约束
)comment '部门表';-- 插入部门数据
insert into dept values (1, '研发部'),(2,'市场部'),(3, '财务部'),(4, '销售部'),(5, '总经办');
id
:部门唯一标识(主键 + 自增)。name
:not null
确保部门名称必须填写(不能为NULL
)。
4. 创建emp
表(员工表)及外键操作
-- 创建员工表
create table emp(id int primary key auto_increment comment 'ID' , -- 主键+自增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' -- 外键,关联dept表的id
)comment '员工表';-- 插入员工数据
insert into emp values
(1, '金庸', 66, '总裁', 20000, '2000-01-01', null, 5), -- 总裁无领导(managerid为null),属于总经办(dept_id=5)
(2, '张无忌', 20, '项目经理', 12500, '2005-12-01', 1, 1), -- 领导是金庸(id=1),属于研发部(dept_id=1)
... -- 其他员工数据
emp
表的dept_id
用于关联dept
表的id
(表示员工所属部门),后续通过外键约束正式建立关联。
5. 外键约束的添加、删除与修改
-- 第一次添加外键约束:关联emp.dept_id到dept.id(无特殊级联操作)
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id);-- 删除外键约束
alter table emp drop foreign key fk_emp_dept_id;-- 第二次添加外键:级联更新和删除(主表操作影响子表)
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id)
on UPDATE cascade -- 当dept.id更新时,emp.dept_id同步更新
on DELETE cascade; -- 当dept的记录删除时,emp中对应记录也删除-- 第三次修改外键:主表操作时子表外键设为NULL
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id)
on update set null -- 当dept.id更新时,emp.dept_id设为NULL
on delete set null; -- 当dept的记录删除时,emp.dept_id设为NULL
- 外键约束名称
fk_emp_dept_id
是自定义的(通常格式为fk_子表_外键列
)。 - 第一次添加的外键无
ON UPDATE/DELETE
,表示若主表dept
的id
被更新或记录被删除,而子表emp
中仍有引用,会直接报错(阻止操作)。 ON UPDATE CASCADE ON DELETE CASCADE
:例如,若dept
表中id=1
(研发部)被更新为10
,则emp
表中所有dept_id=1
的记录会自动变为10
;若研发部记录被删除,所有属于研发部的员工记录也会被删除。ON UPDATE SET NULL ON DELETE SET NULL
:例如,若研发部(id=1
)被删除,emp
表中所有dept_id=1
的员工,其dept_id
会被设为NULL
(表示 “无部门”)。
三、总结
约束是 SQL 中保证数据质量的核心机制:
- 主键、唯一约束确保数据唯一性;
- 非空、检查约束确保数据有效性;
- 默认值约束简化数据插入;
- 外键约束维护表之间的关联完整性,通过级联操作灵活处理主表变更对从表的影响。