文章目录
- 约束简介
- 非空约束
- 检查约束
- 唯一约束
- 列级约束与表级约束
- 给约束起名字
- 主键约束
约束简介
约束是我们在创建表的时候, 我们可以给表中的字段添加约束确保我们的数据的完整性和有效性, 比如大家平时上网时注册用户常见的 : 用户名不能为空, 对不起, 用户名已经存在等提示信息
约束通常包括下面的这6种
约束类型 | 约束关键字 |
---|---|
非空约束 | not null |
默认约束 | default |
检查约束 | check |
唯一约束 | unique |
主键约束 | primary key |
外键约束 | foreign key |
下面我们会详细的剖析这几种约束(默认约束省略, 就是一个简单的在不插入这个字段的数据时插入默认值)
非空约束
这个约束比较好理解, 就是插入的数据不能为空, 当我们设置这一个约束的时候, 我们使用desc展示表结构的时候, 表的Null那一行就会设置为NO, 允许为空就会为YES, 下面是我们的一个实例
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| DEPTNO | int | NO | PRI | NULL | |
| DNAME | varchar(14) | YES | | NULL | |
| LOC | varchar(13) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
尝试完成下面的一个需求, 创建一个学校表, 有编号, 学校名称(不能为空), 建校时间, 这时候就需要给name字段加上一个非空约束not null
我们尝试执行下面的SQL语句
-- 创建一个学校表
create table school(
sno int comment '学校编号',
name varchar(255) not null comment '学校名称',
est_time date comment '建校时间'
);
-- 插入几条数据来进行测试(关于日期类型的插入, 其实底层会进行str_to_date函数的调用, 把字符串转化为日期)
insert into school (sno, name, est_time) values (1, '北京101中学', '1910-08-11');
insert into school (sno, name, est_time) values (2, '南开附中', '1912-04-13');
insert into school (sno, name, est_time) values (3, '清华附中', '1915-03-12');
-- select 查询一下当前的信息
select * from school;
-- 执行结果如下
+------+-----------------+------------+
| sno | name | est_time |
+------+-----------------+------------+
| 1 | 北京101中学 | 1910-08-11 |
| 2 | 南开附中 | 1912-04-13 |
| 3 | 清华附中 | 1915-03-12 |
+------+-----------------+------------+
由于我们添加了非空约束, 也就是我们的name不可以为null, 如果插入一条数据没有name就会报错
-- 尝试执行下面的SQL
insert into school (sno, est_time) values (4, '1899-11-06');
-- 会直接报错, 报错信息如下
ERROR 1364 (HY000): Field 'name' doesn't have a default value
检查约束
其实就是在创建一张表的时候添加一定的检查信息, 这个约束时MySQL8版本之后新添加的, 在先前的版本中是不存在的
基础语法
create table [表名](
...字段信息
check(约束条件)
);
我们尝试建一张学生表, 要求添加学生的年龄必须大于18岁, 这种情况就可以使用检查约束
-- 创建一张学生表
create table t_stu(
sno int,
name varchar(255),
age int,
check(age > 18)
);
-- 执行DML语句
insert into t_stu(sno, name, age) values (1, 'hh', 19);
insert into t_stu(sno, name, age) values (2, 'xx', 18);
-- 第一条是执行成功的, 但是第二条 18 == 18, 不满足check约束, 所以失败
唯一约束
对一个字段添加unique约束, 这个字段就具有了唯一性, 唯一性的字段是可以为null, 但不可以重复, 如果是null的话, 是可以重复的, 我们拿下面的t_stu表作为一个例子说明
# 创建了一个学生表, 这个表的email字段是唯一的, 不可以重复
create table t_stu(
no int,
name varchar(255),
email varchar(255) unique
);
# 我们尝试执行下面的DML语句, 执行成功成功的标明 √, 否则为 ×
insert into t_stu (no, name, email) values (1, 'hh', 'hh@163.com');
insert into t_stu (no, name, email) values (2, 'xx', 'xx@163.com');
insert into t_stu (no, name) values (3, 'xx'), (4, 'wx');
# 查看一下当前的信息
select * from t_stu;
+------+------+------------+
| no | name | email |
+------+------+------------+
| 1 | hh | hh@163.com |
| 2 | xx | xx@163.com |
| 3 | xx | NULL |
| 4 | wx | NULL |
+------+------+------------+
# 尝试插入一条重复的数据
insert into t_stu (no, name, email) values (5, 'sf', 'hh@163.com');
# 直接报错, 因为email的位置重复了
unique约束也可以和not null 同时使用表示非空且唯一
create table t_stu(
no int,
name varchar(255),
email varchar(255) not null unique
);
列级约束与表级约束
如果一个约束紧紧的跟在字段后面, 那这个字段仅仅作用于这一个字段, 我们称之为列级约束, 如果一个约束位于表定义的结尾位置, 那么这个约束我们称之为表级约束, 这种约束可以约束多种字段
unique, primary key, foreign key 可以作为表级约束存在, not null 不可以作为表级约束
我们比较一下下面的SQL语句
# unique的列级约束
create table t_stu(
no int,
name varchar(255),
email varchar(255),
unique(email)
);
# unique的表级约束
create table t_stu(
no int,
name varchar(255),
email varchar(255),
unique(name,email)
);
那么上述列级和表级的约束有什么区别呢?
答案是 : 表级可以联合联合多个字段而列级只能约束一个字段
给约束起名字
约束是以对象的形式存在的, 所有的约束对象对象都存在一个系统表中
information_schema(四个系统数据库之一)中的table_constraints这个表中, 这张表保存的所有的约束名称信息
这里注意, 列级约束是不能起名字的, 但是有系统默认分配的名字, 只有表级别才可以起名字, 如果不起名字的话, 也会自动分配一个
找到约束的名字我们就可以对约束进行删除, 从而消除对某些字段的约束
首先找到这张表
使用这个information_schema数据库
这里面有79张表, 找到这个TABLE_CONSTRAINTS表, 这个表存储的所有的约束对象的信息
desc查看一下表结构, 我们找到刚才的 t_stu 学生表的约束名称
先用DDL语句查看一下创建 t_stu 这张表时的建表语句
我们可以看到, 我们创建表的时候对email字段进行了unique约束, 但是没有给约束起名字, 所以系统会自动分配名字
下面我们查看一下这个约束的名称
这里可以看到这个约束的名称时email
下面我们创建一张新的表, 从新添加一个约束并给约束起名字
基础的语法如下
# 表级约束起名的语法
constraint [约束名称] [表级约束的主体];
# 起约束名的标准
表名_约束的字段_约束的简称(unique/pk/fk)
创建一个班级表进行测试
-- 创建一个班级表(设置班级编号为主键, 班级名称为唯一键)
create table class(
cno int comment '班级编号',
cname varchar(255) comment '班级名称',
constraint class_cno_pk primary key(cno),
constraint class_cname_unique unique(cname)
);
用上面我们找到约束的名称的流程进行演示…
# 使用一下这个系统库
use information_schema;
# 找到class表的约束名称
select constraint_name from table_constraints where table_name = 'class';
这里可能会有疑问为什么给主键起的名字没有生效呢?
下面是我查阅的资料
MySQL版本限制:从MySQL8.0版本开始,主键的名字不再可以直接修改。这是由于 MySQL的内部存储引擎(如InnoDB)实现方式导致的,InnoDB存储引擎中主键的名字是以索引的形式存储的,修改主键名字实际上是修改索引的名字,会对存储引擎的内部数据结构产生影响,因此MySQL禁止直接修改主键的名字。
主键约束
主键约束是一个比较重要的内容
- 主键 : primary key, 简称pk
- 主键约束的字段不能为NULL, 并且不可以重复
- 任何一张表都应该有主键(第一范式), 没有主键的表可以被视为无效表
- 主键值是这行记录的身份证号,是唯一标识。在数据库表中即使两条数据一模一样,但由于主键值不同,我们也会认为是两条完全的不同的数据。
- 主键分类:
- 单一主键(建议使用这种方式)
create table t_student(
id bigint primary key,
sno varchar(255) unique,
sname varchar(255) not null
)
- 联合主键(很少用, 了解)
create table t_user(
no int,
name varchar(255),
age int,
primary key(no,name)
);
- 主键自增
既然主键值是一个自然的数字,mysql为主键值提供了一种自增机制,不需要我们程序员维护,mysql自动维护该字段键自增
create table t_vip(
no int primary key auto_increment,
name varchar(255)
);