在数据库设计中,约束(Constraints)和外键(Foreign Keys)是保证数据完整性和一致性的重要工具。本文将结合代码示例详细介绍MySQL中的主要约束类型以及外键的使用。
约束是对数据库表中列的规则,用于限制数据的类型和范围,确保数据的准确性和可靠性。常见的约束包括:
非空约束(NOT NULL)
非空约束用于确保列的值不能为空,即列的每一行数据都必须有值。
语法:column_name data_type NOT NULL
唯一约束(UNIQUE)
唯一约束保证列中的所有值都是唯一的,即不能有重复值。
语法:column_name data_type UNIQUE
主键约束(PRIMARY KEY)
主键用于唯一标识表中的一条记录,主键要求列的值既唯一又不能为空。每个表只能有一个主键。
语法:column_name data_type PRIMARY KEY
默认约束(DEFAULT)
默认约束为列设置一个默认值,当插入数据时如果没有为该列指定值,则使用默认值。
语法:column_name data_type DEFAULT default_value
检查约束(CHECK)
检查约束用于确保列的值满足特定条件。
语法:column_name data_type CHECK (condition)
外键约束(FOREIGN KEY)
外键用于建立两张表之间的连接,确保子表中的值在父表中存在,以保证数据的完整性。
语法:FOREIGN KEY (column_name) REFERENCES parent_table(column_name)
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 '用户表';
在这个 user
表的定义中:
id
列被设置为主键,且自动递增。name
列要求非空且唯一。age
列有一个检查约束,要求年龄在0到120岁之间。status
列有一个默认值 '1'
。gender
列可以为空。insert into user (name, age, status, gender)
values ('Tom1', 19, '1', '男');
该代码插入一条符合约束条件的记录。
如果尝试插入违反约束的记录,如 name
列为空或 age
列的值超出0到120的范围,将会导致插入失败并抛出错误。
外键是用于在两张表之间建立关系的关键,它确保子表中的值在父表中存在,从而维护数据的完整性。
首先,我们创建了两个表 dept
和 empl
,分别表示部门表和员工表。
创建部门表
create table dept
(
id int auto_increment comment ' ID' primary key,
name varchar(50) not null comment ' 部门名称 '
) comment ' 部门表 ';
创建员工表
create table empl
(
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 ' 员工表 ';
添加外键约束
将 empl
表中的 dept_id
列与 dept
表中的 id
列关联:
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id);
这个外键约束确保了 empl
表中的 dept_id
必须在 dept
表中存在对应的 id
。
MySQL支持在父表记录被删除或更新时对子表中的相关记录进行相应的操作,常见行为包括:
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id) on update cascade on delete cascade;
如果我们改为:
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id) on update set null on delete set null;
那么在 dept
表中的 id
被更新或删除时,empl
表中的 dept_id
则会被设置为 NULL
。
/*
约束 描述 关键字
非空约束 限制该字段的数据不能为null not null
唯一约束 保证该字段的所有数据都是唯一的、不重复的 unique
主键约束 主键使一行数据的唯一标识,要求非空且唯一 primary key
默认约束 保存数据时,如果未指定该字段的值,则采用默认值 default
检查约束 保证字段值满足某一个条件 check
外键约束 用来让两张表的数据之间建立连接,保证数据一致性和完整性 foreign key
*/
-- ------------------------------------------ 约束演示 -----------------------------------------
-- 准备数据
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 '用户表';
-- 插入数据
insert into user (name, age, status, gender)
values ('Tom1', 19, '1', '男'),
('Tom2', 25, '0', '男');
insert into user (name, age, status, gender)
values ('Tom3', 19, '1', '男');
insert into user (name, age, status, gender)
values (null, 19, '1', '男');
insert into user (name, age, status, gender)
values ('Tom3', 19, '1', '男');
insert into user (name, age, status, gender)
values ('Tom4', 80, '1', '男');
insert into user (name, age, status, gender)
values ('Tom5', -1, '1', '男');
insert into user (name, age, status, gender)
values ('Tom5', 121, '1', '男');
insert into user (name, age, gender)
values ('Tom5', 120, '男');
-- ------------------------------------------- 约束(外键)---------------------------------------
-- 准备数据
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, ' 总经办 ');
create table empl
(
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 empl (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);
-- 添加外键
/*
create table 表名(
字段名 数据类型,
...
[cinstraint] [外键名称] foreign key(外键字段名) references 主表(主表列名)
);
alter table 表名 add constraint 外键名称 foreign key (外键名称) references 主表(主表列名);
*/
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id);
-- 删除外键
-- alter table 表名 drop foreign key 外键名称;
alter table empl
drop foreign key fk_emp_dept_id;
-- 删除/更新行为
/*
行为 说明
no action 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 RESTRICT 一致)
restrict 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与 NO ACTION 一致
cascade 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录。
set null 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为nul.(这就要求该外键允许取u1)。
set default 父表有变更时,子表将外键列设置成一个默认的值(Innodb不支持)
ALTER TABLE 表名 ADD ONSTRANT 外键名称 FOREIGN KEY 外字) REFERENCES 丰表名(主表字段名) ON UPDATE CASCADF ON DFIFTF CASCADFI;
*/
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id) on update cascade on delete cascade;
alter table empl
add constraint fk_emp_dept_id foreign key (dept_id) references dept (id) on update set null on delete set null;