文章目录
一、简介
- 为什么需要约束
实体完整性(Entity Integrity)
:例如同一个表中,不能存在两条完全相同无法区分的记录域完整性(Domain Integrity)
:例如年龄范围0-120,性别范围“男/女”引用完整性(Referential Integrity)
:例如员工所在部门,在部门表中要能找到这个部门用户自定义完整性(User-defined Integrity)
:例如用户名唯一、密码不能为空等,本部门经理的工资不得高于本部门职工的平均工资的5倍。
- 查看某个表已有的约束
# information_schema数据库名(系统库)
# table_constraints表名称(专门存储各个表的约束)
SELECT * FROM information_schema.table_constraints
WHERE table_name = '表名称';
二、外键约束
2.1 说明
- 引用说明
- 主表(父表):被引用的表,被参考的表
- 从表(子表):引用别人的表,参考别人的表
- 特点
- 从表的外键列,必须引用/参考主表的
主键
或唯一约束
的列 - 当主表的记录被从表参照时,主表如果要删除数据,需要先删除从表中依赖该记录的数据,然后才可以删除主表的数据
- 从表的外键列与主表被参照的列名字可以不相同,但是
数据类型必须一样
,逻辑意义一致 - 当创建外键约束时,系统默认会在所在的列上建立对应的普通索引
- 删除外键约束后,必须
手动
删除对应的索引
2.2 使用外键
- 添加外键约束
- 建表时
create table 主表名称(
字段1 数据类型 primary key,
字段2 数据类型
);
create table 从表名称(
字段1 数据类型 primary key,
字段2 数据类型,
[CONSTRAINT <外键约束名称>] FOREIGN KEY(从表的某个字段) references 主表名(被参考字段)
);
create table dept( #主表
did int primary key, #部门编号
dname varchar(50) #部门名称
);
create table emp(#从表
eid int primary key, #员工编号
ename varchar(5), #员工姓名
deptid int, #员工所在的部门
foreign key (deptid) references dept(did) #在从表中指定外键约束
# emp表的deptid和和dept表的did的数据类型一致,意义都是表示部门的编号
);
- 建表后
ALTER TABLE 从表名 ADD [CONSTRAINT 约束名] FOREIGN KEY (从表的字段)
REFERENCES 主表名(被引用字段) [on update xx][on delete xx];
ALTER TABLE emp1 ADD [CONSTRAINT emp_dept_id_fk]
FOREIGN KEY(dept_id) REFERENCES dept(dept_id);
- 约束关系
约束关系是针对双方的
- 添加了外键约束后,主表的修改和删除数据受约束
- 添加了外键约束后,从表的添加和修改数据受约束
- 删除主表时,要求从表从表先删除,或将从表中外键引用该主表的关系先删除
- 删除外键约束
# (1)第一步先查看约束名和删除外键约束
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';#查看某个表的约束名
ALTER TABLE 从表名 DROP FOREIGN KEY 外键约束名;
#(2)第二步查看索引名和删除索引。(注意,只能手动删除)
SHOW INDEX FROM 表名称; #查看某个表的索引名
ALTER TABLE 从表名 DROP INDEX 索引名;
2.3 约束等级
约束等级 | 说明 |
---|---|
Cascade | 在父表上update/delete记录时,同步update/delete掉子表的匹配记录 |
Set null | 在父表上update/delete记录时,将子表上匹配记录的列设为null,但是要注意子表的外键列不能为not null |
No action | 如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作 |
Restrict | 同no action,都是立即检查外键约束 |
Set default | 父表有变更时,子表将外键列设置成一个默认的值,但Innodb不能识别(在可视化工具SQLyog中可能显示空白) |
三、其它约束
3.1 非空约束
- 添加非空约束
# 建表时
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型 NOT NULL,
字段名 数据类型 NOT NULL
);
# 建表后
alter table 表名称 modify 字段名 数据类型 not null;
ALTER TABLE emp MODIFY sex VARCHAR(30) NOT NULL;
- 删除非空约束
# 去掉not null,相当于修改某个非注解字段,该字段允许为空
alter table 表名称 modify 字段名 数据类型;
ALTER TABLE emp MODIFY sex VARCHAR(30);
3.2 唯一性约束
- 添加唯一性约束
- 建表时
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型 UNIQUE, # 列级模式
字段名 数据类型
);
CREATE TABLE 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
UNIQUE KEY `key_name` (`field_list`]) # 表级模式(当字段列表长度 >1 时构成复合唯一约束,即多个字段的组合是唯一的)
);
- 建表后
alter table 表名称 modify 字段名 字段类型 unique; # 列级模式
alter table 表名称 add unique key(字段列表); # 表级模式
- 删除唯一性约束
# 若添加唯一性约束时未指定 unique_key_name 则默认为字段名
ALTER TABLE USER
DROP INDEX unique_key_name;
3.3 主键约束
- 添加主键约束
- 建表时
create table 表名称(
字段名 数据类型 primary key, # 列级模式
字段名 数据类型,
字段名 数据类型
);
create table 表名称(
字段名 数据类型,
字段名 数据类型,
字段名 数据类型,
[constraint 约束名] primary key(字段列表) # 表级模式(字段列表可以是一个字段,也可以是多个字段,如果是多个字段的话,是复合主键)
);
- 建表后
ALTER TABLE 表名称 ADD PRIMARY KEY(字段列表);
- 删除主键约束
alter table 表名称 drop primary key;
3.4 自增约束
- 说明
- 一个表最多只能有一个自增长列
- 自增长列约束的列必须是键列(主键列,唯一键列)
- 自增约束的列的数据类型必须是整数类型
- 如果自增列指定了 0 和 null,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值。
- 指定自增约束
- 建表前
create table 表名称(
字段名 数据类型 primary key auto_increment,
字段名 数据类型 unique key not null,
字段名 数据类型 unique key,
字段名 数据类型 not null default 默认值,
);
create table 表名称(
字段名 数据类型 default 默认值 ,
字段名 数据类型 unique key auto_increment,
字段名 数据类型 not null default 默认值,,
primary key(字段名)
);
- 建表后
alter table 表名称 modify 字段名 数据类型 auto_increment;
- 删除自增约束
alter table 表名称 modify 字段名 数据类型; # 去掉auto_increment相当于删除
3.5 检查约束
mysql> CREATE TABLE employee(
-> eid INT PRIMARY KEY,
-> ename VARCHAR(20),
-> gender VARCHAR(20) CHECK(gender IN ('male', 'female')),
-> age TINYINT CHECK(0 <= age <= 150)
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> SHOW CREATE TABLE employee\G
*************************** 1. row ***************************
Table: employee
Create Table: CREATE TABLE `employee` (
`eid` int NOT NULL,
`ename` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
`gender` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
`age` tinyint DEFAULT NULL,
PRIMARY KEY (`eid`),
CONSTRAINT `employee_chk_1` CHECK ((`gender` in (_latin1'male',_latin1'female'))),
CONSTRAINT `employee_chk_2` CHECK (((0 <= `age`) <= 150))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1 row in set (0.00 sec)
mysql> INSERT INTO employee VALUES (1, 'rayslee', 'male', 100), (2, 'monica', 'female', 18);
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> INSERT INTO employee VALUES (1, 'joshua', 'secret', 200);
ERROR 1264 (22003): Out of range value for column 'age' at row 1
mysql> INSERT INTO employee VALUES (1, 'joshua', 'secret', 100);
ERROR 3819 (HY000): Check constraint 'employee_chk_1' is violated.
mysql>
3.6 默认值
- 为字段添加默认值
- 建表时
# 说明:默认值约束一般不在唯一键和主键列上加
create table 表名称(
字段名 数据类型 primary key,
字段名 数据类型 unique key not null,
字段名 数据类型 unique key,
字段名 数据类型 not null default 默认值,
);
- 建表后
alter table 表名称 modify 字段名 数据类型 default 默认值;
# 如果这个字段原来有非空约束,你还保留非空约束,那么在加默认值约束时,还得保留非空约束,否则非空约束就被删除了
# 同理,在给某个字段加非空约束也一样,如果这个字段原来有默认值约束,你想保留,也要在modify语句中保留默认值约束,否则就删除了
alter table 表名称 modify 字段名 数据类型 default 默认值 not null;
- 删除默认约束
alter table 表名称 modify 字段名 数据类型 ;#删除默认值约束,也不保留非空约束
alter table 表名称 modify 字段名 数据类型 not null; #删除默认值约束,保留非空约束