给数据“立规矩” —— MySQL 新手必学的表约束全指南

🔥海棠蚀omo:个人主页
❄️个人专栏:《初识数据结构》,《C++:从入门到实践》,《Linux:从零基础到实践》,《Linux网络:从不懂到不会》,《MySQL:新手入门指南》
✨追光的人,终会光芒万丈
博主简介:

目录
前言:
在上一篇文章中我们讲解了MySQL中的各种数据类型,那么正是因为有了各种数据类型,才会有今天我们要讲的表的约束相关知识,那么这中间到底是怎么回事呢?下面我们就一起来看看吧。
一.为什么要有表的约束?
在上一篇文章中,我们认识了很多的数据类型,并在它们的下面我们也通过例子进行了演示,而在这些例子中我们不乏向表中插入一些不合法,或者说超出范围的数据。
而结果我们当时也看到了,MySQL是会拦截我们的,那么MySQL为什么会拦截我们呢?
答案就是我们要插入的数据是不符合当前数据类型的,那么换句话说数据类型在无形中对我们程序员就形成了一种" 约束 ",只要插入的数据不在" 约束 "之内,那么MySQL就会进行拦截。
所以我们就可以回答上面的问题了:为什么要有表的约束?
答案就是通过约束,可以保证我们未来插入数据库表中的数据是符合预期的。而约束的本质就是通过技术手段,倒逼程序员插入正确的数据。
那么反过来,站在MySQL的角度,凡是插入进来的数据,都是符合数据约束的!!!
二.表的约束
那么上面在介绍了为什么要有表的约束之后,我们也要知道:单单只通过数据类型来进行" 约束 "是不够的,还需要有更多的约束条件。
所以下面我们就来讲解一些常见的约束条件。
2.1空属性
一般有两个值:null(默认的)和not null(不为空)

与之相关的其实就是我们使用desc指令查看表的属性中Null这一列,默认情况下这一列的内容都是:YES,表示的就是这一行所对应的那个属性数据可以为空。
那么怎么让一个属性的数据不能为空,即not null,并且设置为not null后又有什么表现呢?下面我们通过一个例子来演示:

我们这里创建一个表,在表的属性后面加上not null就可以将该属性设置为not null(不为空),并且我们再次通过desc指令来查看表的属性,可以看到Null这一列的内容就不再是YES,而是NO,即该属性对应的数据不能为null。
那么下面我们就来验证一下:


那么当我们向其中添加数据的时候可以看到,如果我们想要插入的数据是NULL,也就是为空,那么MySQL是会拦截我们的,并且报的错误说明的也很明显:name,id这一列不能为空。
2.2默认值
默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性地使用默认值。
这个默认值我们其实就可以将其认为是C++语法中缺省值,当我们没有传入该参数的实参时,就会使用我们在声明或者定义时所设定的缺省值,对于这点相信大家都能理解。
而默认值这一选项在表的属性中也是出现的了,我们来看:

Default这一列表示的就是默认值,可以看到再上一个我们创建的表中,name和id属性都没有设置默认值,所以这一列的内容全部都是NULL。
那么下面我们通过一个例子来看看默认值是怎么设置的以及设置之后又有什么表现:

那么这里我们创建了一张表,设置默认值的方法就是在属性后面加上:default + 默认值,通过这种方式我们就能够设置默认值。
那么下面我们插入一些数据来看一下:


在上面我们插入了不同的数据,有的属性我们在插入时并没有显示的传入,但是从结果来看我们也成功地插入了数据,并且那些没有显示插入的数据,用的就是我们在创建表的时候设置的默认值。
而在上面我们其实也看到了最后一个属性number我们在设置的时候用的是:not null default 123456,那么这里可能有人就有疑问了:not null和default这两个不冲突吗?
其实是不冲突的,反而它们两个是互补的,这里我们既要说一下它们两者之间的区别:not null的前提是向表中插入数据,但是插入的数据不能为空,而default是不向表中插入数据,那么才会使用default。
并且MySQL是支持我们上面的那种写法的,即not null + default,这种写法就是如果要插入数据,那么插入的数据不能为空,如果不插入数据,那么就使用默认值。
那么下面我们针对这种特殊的写法与单独的not null比较一下来看看区别:

第一条我们插入的数据就是来检测number属性的not null,可以看到是没有问题的,我们是无法传入NULL的。
而第二条我们插入数据时并没有打算插入name属性的内容,可以看到报的错误变成了name属性没有默认值,而不是name属性的内容不能为空。
所以通过第二个例子我们其实就证明了not null和default二者是不冲突的,并且是互相补充的。
2.3列描述
列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解。
这个列描述其实我们在之前就已经见过了,下面我们再来回忆一下:

就是我们在创建表的时候后面加的comment,通过comment描述,我们其实就能知道所对应的属性是干什么的。
并且通过desc指令我们是看不到属性所对应的comment描述的,那么我们要想看到该怎么做呢?我们来看:

我们可以通过show指令来查看一个表被创建的相关语句,那么在上图我们就可以看到每个属性的comment描述。
但是经过我们上面的描述也可以发现列描述并没有像not null,default那种不满足条件时MySQL会拦截我们报错的情况,而只是给程序员描述该属性是什么含义。
2.4zerofill
zerofill其实跟我们上一篇文章讲解数据类型有些关系,我们先来看一种现象:


当我们通过show指令再次查看创建表时的信息的时候,我们可以看到int类型的后面跟了一个(10),那么这个10代表什么意思呢?
那么要想知道这个问题的答案,我们就需要来介绍一下zerofill关键字。


首先我们先更改一下a属性的类型,在其后面加上zerofill关键字,目前我们还看不到有什么区别,下面我们向其中插入一些数据再来看看:


那么当我们向里面插入一些数据后,查看表中的数据,可以发现a的数据从123变为了0000000123,下面的1234也是如此。
而出现这种现象的原因正是因为zerofill起作用了,int后面括号中的10,表示的是宽度为10,而zerofill的作用就是:如果插入的数据宽度小于10,那么就会在前面的空位上自动补0。
对于这点我们要注意,这只是最后显示的结果,实际在MySQL中存储的依旧是123和1234,所以我们不必担心使用zerofill后实际存储的值会发生变化。
那么这里就会有一个问题了:如果插入的数据宽度超过了int后面括号中的数字呢?
那么对于这个问题,我们下面再通过一个例子来观察:
那么在上面我们手动修改a属性的类型,将其int后面括号内的数字改为4,那么下面我们再向其中插入一些数据看看:
从结果中我们可以看到当我们插入的数据的宽度>=int括号中的数字的时候,就不再自动补0了,此时就和我们不加zerofill是一样的效果了。
那么相信大家心中还会有一个疑惑:为什么int类型括号后面的数字默认是10呢?
我们只要思考int类型的范围是多少其实答案就已经出来了,即-2的31次方到2的31次方-1,也就是-21亿~21亿,那么21亿这个数字的宽度是多少呢?
答案就是10位,这个10对应的正是int括号中的10,所以此时我们就能理解这个10是怎么来的了。
最后补充一点,在上面我们设置a和b的类型的时候,我们在后面加上了unsigned,所以int后面括号中的数字是10,如果我们把unsigned去掉,那么括号中的数字将会变为11。
原因就是加上unsigned表示无符号,而去掉unsigned后将变为有符号,所以会多个符号位,也就从10变为了11。
2.5主键
主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型。
那么下面我们直接通过一个例子来看一看主键是如何进行设置的以及设置之后会有什么效果:

设置的方式很简单,在属性的后面加上:primary key即可将该属性设置为主键,并且我们通过desc指令查看表的属性,可以看到id属性在设置了主键后,就不能再为空了。
那么下面我们向其中插入一些数据来看看:

从上面的结果中我们可以看到当我们想要插入相同id的数据的时候,MySQL就会拦截我们了,因为主键属性是不能重复的!!!
那么如果我们创建表的时候并没有设置主键,在后面要想将表中的某个属性设置为主键该怎么做呢?我们来看:

这里我们创建一张表,通过desc指令我们可以看到此时的表中没有主键属性,那么下面我们就来将id属性设置为主键:


要想完成这个操作我们就要用到alter指令,并且后面要使用add,表示要向表中添加一个主键,在括号中填入我们要设置的属性。
通过这个指令我们就可以成功地将id属性设置为了主键,那么既然我们能够添加主键,未来我们要想将主键从我们的表中剔除掉呢?或者说如何删除主键呢?

同样是通过alter指令,不过后面的add要变为drop,通过这个指令我们就可以成功删除一个表中的主键。
2.5.1复合主键
那么在主键这一块我们再补充一点知识,那么就是复合主键,那么复合主键是什么意思呢?
复合主键就是在创建表的时候,在所有字段之后,使用primary key(主键字段)来创建主键,如果有多个字段作为主键,可以使用复合主键。
那么不废话,下面我们直接通过例子来看一看:


那么设置复合主键的方式就是在创建表的最后加上:primary key(属性名),在上面我们就将id和course属性一同设置为了主键,那么下面我们来插入一些数据来观察一下:


看了上面的结果,相信大家心中都会有疑惑:在上面的例子中,id重复了,course也重复了,但是却都能成功插入数据,主键不是不能重复吗?
答案就是如果设置了复合主键,那么只有当全部属性都重复了才会触发主键不能重复的机制,那时MySQL才会去拦截我们,从上图我们也能看到确实是如此。
那么对于复合主键相信大家还有一个最大的问题:主键不是只能有一个吗,怎么还能将多个属性设置为主键呢?
答案就是确实主键只能有一个,但是谁说主键所指向的属性只能有一个了?
2.6自增长
auto_increment:当对应的字段,不给值,会自动地被系统触发,系统就会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。
那么下面在演示之前我们先了解一下auto_increment的特点:
1.任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
2.自增长字段必须是整数
3.一张表最多只能有一个自增长
那么在上面知道了auto_increment的特点后,下面我们就直接来通过一个例子来看看它该怎么是使用:

在上面我们在创建表的时候,就将id属性设置为主键,并在其后面加上了auto_increment。而下面我们通过desc指令来查看表的属性的时候,可以看到在id属性后面的Extra一栏中多了auto_increment。
那么下面我们就向其中插入一些数据来看看效果:



从上图可以看到,我们只向表中插入了name这一列的数据,但是从结果来看,id这一列不仅有数据,而且还进行了自动+1的操作,可以看到我们插入了五个数据,id也是从1到5。
那么这个时候我们就有疑问了:那我要是主动插入id这一列的数据呢?下面我们就来试一试:

而当我们手动插入了一个id数据1000后,后面我们依旧只传name属性的值,但是从上图中我们可以看到后面我们再插入值,就不再从6开始了,而是从1001开始,那么自增长的起始数据到底该怎么查看呢?

我们通过show指令就可以知道答案,可以看到在上图中AUTO_INCREMENT=1004,这就是答案,下个id属性的值就是1004,就是根据这个信息来获取的。
2.7唯一键
一张表中往往有很多字段都需要唯一性,数据不能重复,但是一张表中只能有一个主键,所以我们该如果保证其他字段的唯一性呢?
答案就是通过唯一键,唯一键和主键差不多,但是唯一键允许为空,而且可以多个为空,空字段不做唯一性比较 。
那么下面我就通过一个例子来带大家理解何为唯一键:

在上面创建的表中,我们将telephone属性设置为了唯一键,因为每个人的电话号码都是不一样的,所以我们要维护telephone的唯一性。
那么下面我们就向其中插入一些数据来观察一下:

在上图中我们向表中插入了几组数据,可以看到telephone属性在设置为唯一键后,确实不能重复,并且也确实可以为空,为空不做唯一性判断也是证明了的。
5.8外键
我们要知道MySQL是关系型数据库,那么这个关系体现在哪儿呢?
答案就是体现在表与表之间的关系,而用于表与表之间关系的就有我们要讲的外键,那么什么叫做外键呢?
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。
这么说可能不太好理解,下面我们来看一张图:

在上图中有两张表,第一张学生表中的class_id和第二张班级表中的id指的都是同一个内容,那么stu和myclass这两张表就有外键关系了,并且班级表是主表,学生表是从表。
但是只有外键关系是完全不够的,只有外键之名,并没有外键之实,也就是没有外键约束,举个很简单的例子:如果我们向学生表中插入了一组数据,class_id是30,那不就出问题了吗?
就没有id为30这个班级,又怎么会有这个学生呢?
所以为了维持这种合理的外键关系,需要我们通过外键约束来进行实现,那么该如何做呢?

对应的语法就如上图所示,那么下面我们就根据上面的例子来演示一下:



那么在上面我们创建了这两张表,并建立了外键约束,那么下面我们就向表中插入一些数据看看:

可以看到,当双方的信息保持一致的时候,是可以正常插入数据的,那下面我们就来试一试外键约束到底行不行:

从结果可以看到当我们插入的数据class_id超出了范围之后,MySQL就开始拦截我们了,就没有教室名为3和4的,哪儿会有王五和赵六这两个学生呢?
并且我们此时如果想要删除myclass表中id为1的这一列数据是不行的,MySQL依旧会拦截我们,因为教室id为1的还有学生呢。
我们如果想要删除的话就要先把student表中class_id为1的数据先删除完了,才能够删除myclass表中id为1的信息。
所以外键约束其实并不只是主表对从表的约束,而是双方互相约束:主表约束从表不能无中生有,而从表约束主表不能" 始乱终弃 "!!!
以上就是给数据“立规矩” —— MySQL 新手必学的表约束全指南的全部内容。