【MySQL】表的约束

前言

前面我们在介绍创建表的时候,我们只介绍了Field、Type但是后面的几个,如: Null、Key、Default等没有提过,本期就来介绍他们!

目录

前言

一、约束的概念

二、空属性

三、默认值

四、列描述

五、zerofill

六、主键

七、自增长

八、唯一键

九、外键


一、约束的概念

约束(Constraint)是数据库中用于限制表中数据的一种机制。它确保数据库中的数据符合特定的规则和条件,从而保证数据的完整性和一致性。约束可以在创建表时定义,也可以在表创建后添加或修改(一般建议在创建表时就添加好)。

• MySQL中真正的约束字段是数据类型,当进行插入数据的时候超过范围,MySQL会直接拦截操作,提高了插入数据的正确性

• 但是数据类型的约束太单一,必须还要其他的约束,从业务逻辑的角度保证数据的正确性

• 约束的目的是:保证插入数据库的数据的完整性和可预期性

• 约束的本质是:从技术的角度倒逼程序员插入正确的数据,尽可能保证数据的完整性和可预期性

表的约束很多,这里主要介绍如下几个常用的:

null / not null	 	# 空属性约束
default 	     	# 默认值约束
comment	    	 	# 列描述约束
zerofill		 	# 补零约束
primary key		 	# 主键约束
auto_increment	 	# 自增约束
unique key		 	# 唯一键约束

二、空属性

• 空属性有两个值:null (空,默认)和 not null (非空)

• 数据库默认允许字段是为空的,但实际开发中,尽可能的保证字段不为空,因为数据为空无法参与计算。

先来看看,空值无法参与计算:

下面我们使用一个实际的案例,演示一下非空属性 not null

创建一张学生信息表,包含学生姓名、班级名、性别;其中姓名和班级必须是非空的。

先来全列插入:

此时,因为性别是没有设置非空的所以可以省

但是 name class_name 不可以省略的,一旦省略就会直接报错:

三、默认值

• 某一种数据会经常行的出现某个具体的值,可以在一开始使用default指定一个默认值。

• 如果字段设置了 default,用户将来插入时,如果有具体的数据,就用用户的,否则就用默认的。

• 这个就和我们C++中的缺省参数很相似,用户指定了就是用用户指定的,否则就是用默认值。

• 如果在建表时,没有给字段指定默认值,也没有给字段设置为 not null,那么 MySQL 会自动将 null 设置为该字段的默认值

先来创建一张表演示一下默认值属性的使用:

也可以使用 show create table t2 \G 来看:

下面我们插入数据的时候,可以不带性别:

default 和 not null 同时设置

• 因为有了default之后,该字段一定有默认值了,也就是一定不为空了,因此如果default和not null同时设置了,not null就没有意义了。

此时age和sex的not null是无效的:

但是此时age和sex是允许插NULL的:

正确的看待 not null 和 defualt的关系

not null default 是不冲突的,而是互补的!

not null 是当用户想插入时,插入的数据必须是非空的,即合法的数据。

default 是当用户忽略这一列时,使用默认值。

• 当有default 值时,可以不用指定数据,不管是null还是not null ; 但如果是指定了且是被not null修饰的,此时要求的数据必须是合法的,否则直接报错!

• not null default 一般很少一起出现

四、列描述

• 列描述 comment 没有实际含义,专门用来描述字段,会根据创建表语句保存,用来给程序员或者DBA来进行了解的。(类似于语言上的注释)

• 当程序员看到这些信息之后,就能大概确定对应字段的具体描述是什么,相当于一种软性约束

使用 show create table t4 \G 可以看到comment描述:

五、zerofill

很多人在刚开始学数据库的时候对类型后面括号中的数字长度很不理解,如:int(10),int不是4个字节吗?10又是啥意思呢?

• 数字类型后面的长度表示至少显示的宽度,例如:int(5) 就代表不足5位了,前面用0补齐5位, 当超过5位时不做处理;

• 上面补齐的前提是,字段设置了 zerofill 约束,如果没有设置则这个括号里的数字无意义。

我们创建一张表,里面只有2个字段int 和 int(5)使用zerofill约束,看看他的显示是咋样的:

我们可以看到,当使用 zerofill 约束后,int 就会变成 unsigned 的!

此时,插入负数是插入不进去的:

我们把num2换成1:

这里再试一下,超过5位的,此时应该就是不做处理:

这里需要注意的是:zerofill 补0 是MySQL的显示格式,实际在数据库中存储的还是1,我们可以使用hex函数证明:

六、主键

主键primary key 用来唯一的标识表中每一行字段的约束设为,主键的字段 不能重复、不能为空,一张表中最多只能有一个主键,主键所在的列通常是整数类型

• 虽然主键一张表中只能有一个,但是并不意味着主键只能给一列添加,也可以是多列组合成的主键,这就是后面介绍的复合主键

添加主键的方式有两种:1、创建表的时候指定主键 2、通过 alter table 添加

(添加主键的方式可以直接跟在字段的后面,也可以最后使用 primary key(val...)设置)

建议:尽量在创建表的时候指定好主键!

主键使用案例:

创建一张表,里面有两个字段:1、id表示学生的学号 设为 唯一标识学生的主键  2、name 学生姓名不能为空。

此时,我们给id设置了主键,也就是后面插入时每个学生的 id 是不能一样的:

此时因为id是主键具有唯一性,也可以使用主键值唯一查到相关的而数据:

新表添加主键

当创建表了但是该表没有设置主键,我们可以使 alter table 的方式添加主键

alter table 表名 add primary key(字段列表);

这张表就是创建好了但是没有主键,我们此时可以将 id 设置为主键:

删除主键

alter table 表名 drop primary key;

加上上面的 t7表中我不想要主键了,我就可以删除掉:

这里有个细节:我们发现我们一开始创建t7的时候id是NULL的,添加完id为主键之后是非空的,这符合主键,但是将主键删除了不应该id是NULL的吗??

因为删除主键不会自动将主键的not null 属性移除!所以这里看到的就是删除id的主键约束之后,id依然是非空的!

复合主键

• 虽然一张表最多只能由一个主键,但并不表示一个表中的主键只能添加给一列,可以有多个字段共享一个主键,这种就叫做复合主键

• 表中被设置了复合主键的这多个字段,不能同时重复也不能为空。

• 设置了复合主键后,被设置复合主键的多个字段合起来才是一个主键

primary key(字段名1, 字段名2, ..., 字段名n)

创建一张表t8,表示学生的选课情况表。里面有三个字段:id表示学生的学号,course表示学生所选的课,score表示学生的成绩。这种情况下,每个学生只能选择一门课,所以id和course不能同时出现一样的,所以可以将它两设置为复合主键!

此时,id和course不能为空,且不能同时有两组id和course的数据被插入,一旦第二次有id和course相同的数据插入时,MySQL就会拦截报错!

关于表创建后添加复合主键和删除复合键的操作和上面的一模一样,这里不再介绍了!

七、自增长

auto_increment: 当对应的字段被设置为自增长后,不给值时会自动被系统触发,系统会从当前字段中已经有的最大值+1,得到一个新的不用值。

• 自增长通常和主键搭配使用,作为逻辑主键。

• 一般而言,建议将主键设计成与当前业务无关的字段,避免因为业务逻辑的调整而需要修改主键。

自增长的特点

• 任何一个字段都要做自增长,前提时本身是一个索引(key一栏有值)

自增长的字段必须是整数

• 一张表中最多只能有一个自增长

自增长的使用案例:

我们在插入时省略不写id时,他会自动的从当前最大的id+1开始使用,一开始默认是0:

当然我们可以在创建表的时候指定,当前表的aoto_increment可以使用show查看:

我们再来创建一个字段一模一样的t0表,然后一开始指定auto_increment的值默认是100:

我们再来插入三个:

这里还有最后一个要验证的:上面说了如果不指定会从当前的最大值+1开始,那我现在的问题是,上面的id是100、101、102,此时如果我手动的想t10中插入一个888的数据,那下一次是不是从889开始的呢?

如果不写,果然是从当前表中最大的值+1开始的!

其实这里有一个函数:last_insert_id() 用来查询上一次的最后插入时的auto_increment的值的:

八、唯一键

一张表中通常有很多字段的数据都是不能重复的,这些字段也需要有唯一性,但一张表又只能有一个主键,此时就需要拿出唯一键 unique。注:unique key 可以简写成 unique
• unique 唯一键的本质和主键差不多,都能够保证字段中数据的唯一性,但唯一键允许字段为空,且可以多个字段为空,空字段不做唯一性比较
唯一键并不能保证录入的数据一定是正确的,只能保证能够录入到表中的数据是合法的。
例:在录入数据时,录入数据的人就是把数据填错了,但这个数据又恰好不与表中的其他数据冲突,这个数据就是合法但错误的。

主键和唯一键的区别:

1、主键更多的是用来标识唯一性,而唯一键更多的是保证在业务上不和别的信息重复。

2、主键只能有一个,而唯一键可以有多个

3、建议将主键设计成和当前业务无关的字段,这样,当业务调整的时候,可以尽量不会对主键做过大的调整 。

举个例子理解:

某公司需要有一个员工管理系统,系统中有一张员工表,表中有两列信息,分别是身份证号、员工工号,可以选择身份证号作为主键。但是在设计员工工号的时候,也需要一种约束保证所有员工的工号不能重复。这里的唯一键约束具体指的就是在公司的业务上不能重复,在设计表的时候需要这个约束,因此就能将员工工号设计成唯一键。


我们下面创建一张表t11,里面三个字段:id表示某个的排队号,name表示为名字,stu_num表示学号。其中id设置为主键且自增,name不为空,stu_num为唯一键!

主键id因为设置了自增,所以我们可以不管!name 必须要设置,唯一键stu_num的话可以为空,但是如果不为空的话必须不能和表中已有的数据重复!

这里还有个细节:我们最后一次插入的id是4,但是我们直插入了3条数据!原因是,我们插入失败了一次即2号id被占了,倒数第二条就是3,最后一次就是在上一次的基础上+1,所以最后一次的插入就是4!

九、外键

• 外键用于定义主表和从表之间的关系,外键约束主要定义在从表上,主表必须有主键/唯一键约束

• 当定义外键后,要求外键列数据必须在主表的主键列存在/null(唯一键)

• 外键更强调的有两点:表跟表之间的关联、表跟表之间的约束

语法

foreign key (从表字段名) references 主表名(主表字段名)

我们按照上述的图结构建表:

1、创建主表

2、创建从表

3、想主表和从表插入数据

演示插入一个主表的id不存在的情况,直接报错!

4、插入一个学生,但是班级可以为空,此时可以理解为,该同学还未分班

5、此时如果我们删除myclass中id为11的班级,此时因为外键的原因即还有学生所属他,所以他是删不掉的:

这也是外键带来对的优势,那就是误删是会帮我们检查!

6、要想删除 myclass中id为11的班级,此时需要我们把所属他的数据全删掉:

理解外键约束

这个世界是数据很多都是相关性的。在上述例子中,如果没有创建外键约束,就能在没有对应班级 id 的情况下,却能将学生插入到不存在的班级。或者某个班级在还有学生的情况下,却能直接将对应 id 的班级删除掉,学生还在呢,班却没了。这两种情况显然都是不合理的,因为此时两张表在业务上是有相关性的,但是在业务上没有建立约束关系,那么就可能出现问题。解决方案就是通过外键完成的。建立外键的本质其实就是把相关性交给 MySQL 去审核,提前告诉 MySQL 表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,MySQL 就会拦截用户的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值