MySQL之表的约束
🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【MySQL的学习】
📝📝本篇内容:基本概念;null空属性;default默认值;列描述;zerofill;主键;自增长;唯一键;外键
⬆⬆⬆⬆上一篇:MySQL内置函数
💖💖作者简介:轩情吖,请多多指教(>> •̀֊•́ ) ̖́-
1.基本概念
在我们数据库的表中一定要有各种约束,通过约束,让我们未来插入数据库中的数据是符合预期的。约束本质是通过技术手段,倒逼着程序员,插入正确的数据。反过来,站在mysql的视角,凡是插入进来的数据,都是符合数据约束的,可预期的。总的来说约束的终极目标就是保证数据的完整性和可预期性。
真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。
表的约束很多,这里主要介绍如下几个: null/not null,default, comment, zerofill,primary key,auto_increment,unique key 。
2.null空属性
两个值:null(默认的)和not null(不为空)
数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办
法参与运算。not null这个字段永远不能存 NULL(空值)



如果我们没有设置任何属性,就是null并且会给我的default属性设置为NULL。先不管default属性,总之我们没有设置null,我们插入时可以省略字段。

创建一个班级表,包含班级名和班级所在的教室。
站在正常的业务逻辑中:
如果班级没有名字,你不知道你在哪个班级
如果教室名字可以为空,就不知道在哪上课
所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这就是"约束"。


在上面的insert语句中,我们正常的插入数据,不缺少字段,就没有任何问题,但是当我们在班级和名字和教室中任意一个缺少时,就会出现无法插入的情况,报错说是没有一个默认值。因为还没讲default,所以说可能还不能理解什么意思,反正就是无法插入。

在我们进行插入时,其实就两种情况:NULL,合法数据。但是我们尝试在字段设置为not null属性下插入NULL,会失败。
3.default默认值
默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。


通过上面的演示,我们可以清楚的发现
如果设置了default,用户插入时,如果有具体的数值就用用户的,没有就用默认的


上图中,我们一开始对设置了not null的gender字段插入NULL,结果失败了,说是不允许为NULL,当第二次插入时,我直接缺少了这个字段,它报的错就是缺少默认值。因此当我们对字段设置了not null,然后此时没有明确指定一列要插入,用的就是default,如果建表中,对应列默认没有设置default值,无法直接插入。在第三次插入时,缺少了age,但是成功,因为它虽然设置了not null,但是default我们也进行设置了。
这也说明了default和not null不冲突,而是互相补充的。并且我们的default并不关心not null还是null,因此在缺少字段插入时,只看default的内容
还有一个要注意就是我们desc table 时显示出来的Default一列中的NULL会有点歧义,就以上面的图片为例子
你看到的两个 Default: NULL 只是显示长得一样,实际意思完全不同:
gender(NOT NULL)的 Default: NULL → 只是 "没给它设默认值",MySQL 只是用了同一个 "标记",但因为加了 NOT NULL,插入时必须手动填值,绝不能填 NULL;
name(允许 NULL)的 Default: NULL → 是 "真默认值",插入时不填就自动存 NULL。
4.列描述
列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA来进行了解。

我们可以正常插入,但是没有通过这些方法查看我们设置的列描述,只能通过查看表创建语句

5.zerofill
在有的版本的数据库中,建表后查看会发现整数类型后面有数字,不知道是什么。我这边演示一下(我的版本没有,在在 MySQL 5.7 及更早版本中有)
接下来测试一下,在没有使用zerofill和使用zerofill会有什么区别
首先,我们可以发现一开始我的版本是不显示int(10)的,当将字段类型后面加上zerofill之后就显示了,并且我们的字段apple也发生了变化,多了好多0,仔细数一下就可以发现,一共10位,这个时候我们就可以明白int(10)代表的是显示宽度。其实没有zerofill这个属性,括号内的数字是毫无意义的。还有一点就是我们的int一开始是没有添加unsigned,现在居然给我自动加上了,因为zerofill的作用是用前导零填充数字到指定长度,这通常用于非负数字的格式化显示。因此,MySQL 认为使用 zerofill的字段不应该存储负数,所以自动将其设置为 unsigned。

可以我们将宽度进行修改后并不会影响我们的数据,这个宽度数字是
至少的含义,也就是至少宽度数字长度,超过了就不管了,不满就使用0补齐。不过要注意的是,无论宽度怎么修改,这只是最后显示的结果,在MySQL中实际存储的还是1。为什么是这样呢?我们可以用hex函数和where查找来证明。

可以看出数据库内部存储的还是1,00001只是设置了zerofill属性后的一种格式化输出而已。
还有一个要解释的就是在一开始放的图片中,说有的版本中可以在没有使用zerofill时就可以显示宽度数字,其中int为11,int unsigned为10,这主要是因为有符号 int 的最小值是 -2147483648,这个数包含负号一共是 11 个字符(- + 10 位数字),所以 MySQL 把默认显示宽度设为 11,刚好能完整显示这个最小值。int unsigned默认 10:无符号int 没有负号,最大值是 4294967295,一共是 10 个字符,所以默认显示宽度设为 10,刚好适配这个最大值。int加了zerofill后,MySQL 自动转成 int unsigned,原本int的默认 11 → 变成 int unsigned 的默认 10;但没指定显示宽度时,MySQL 有时会保留 "兼容显示"(比如显示 11),本质还是适配最大显示长度的逻辑。
6.主键
主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型


这边很好理解,id字段不能重复,此时我们可以使用命令将id字段的主键属性去除
bash
alter table 表名 add primary key(字段列表) 当表创建好以后但是没有主键的时候,可以再次追加主键
alter table 表名 drop primary key; 删除主键


复合主键:在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键。这边要注意一个表中只有一个主键,不意味着一个表中的主键只能添加给一列,也可以添加到多列上,就是复合主键。



可以看到我们这边的复合主键再判断重复时,必须要同时满足两个字段都相同才会报错,否则还是可以插入成功的。不管怎么说,复合主键其实还是一个主键,只不过是有两个字段组成在一起的。
7.自增长
auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键。
自增长的特点:
任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
自增长字段必须是整数
一张表最多只能有一个自增长

那此时如果我突然想要插入id会发生什么呢?下一个插入依旧没有指定id字段,我们的id会按照哪种方式增加下去呢?

可以看到,它会按照我们插入后的字段数据进行递增,其实还有一种方法可以查看下一个递增的整数

我们在创建时也是可以自己设置的


bash
select last_insert_id(); 在插入后获取上次插入的 AUTO_INCREMENT 的值(批量插入获取的是第一个值)
前面提到了索引,这边简单理解一下,后面会讲,索引:索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
8.唯一键
一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键:唯一键就可以
解决表中有多个字段需要唯一性约束的问题。
唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较



关于唯一键和主键的区别:
我们可以简单理解成,主键更多的是标识唯一性的。而唯一键更多的是保证在业务上,不要和别的信息出现重复。乍一听好像没啥区别,我们举一个例子

假设我们的业务是要存储班级学生的id,name和tele,但是我们的id和tele肯定是每个人都不一样的,我们可以选择id作为主键,而我们学生id的时候,需要一种约束:而所有的学生id都不能重复。具体指的是在公司的业务上不能重复,我们设计表的时候,需要这个约束,那么就可以将员工工号设计成为唯一键。因此可以理解为主键和唯一键是互补的。
一般而言,我们建议将主键设计成为和当前业务无关的字段,这样,当业务调整的时候,我们可以尽量不会对主键做过大的调整。
其实我们也可以将我们的唯一键设为not null,这样它其实和主键的技术层面是一样的了

9.外键
外键用于定义主表和从表之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或unique
约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。
bash
foreign key (字段名) references 主表(列)
我们举个例子来理解一下,我们创建一个班级表和学生表,我们这两个表之前是相关的,我们的学生信息中的class_id代表着我们所在的班级的id,这个字段也是班级表中的字段,如下面演示,理论上,我们不创建外键约束,就正常建立学生表,以及班级表,该有的字段我们都有。

但是这个时候,假设我们的管理数据库的人进行操作时失误了,当我们对于一个学生数据进行插入时他的class_id我们使用了一个不存在的班级,或者我们在删除班级表class中的某一行时忘记了还有学生的存在,那么此时我们的学生就在一个不存在的班级。这样的情况可能发生吗?绝对不可能!!!

也就是现在两个表之间只有从从表和主表的关联关系,因此现在需要让他们产生约束,即使用外键


此时我们无法插入不存在的班级,包括当我们的班级有对应的学生时无法删除
建立外键的本质其实就是把相关性交给mysql去审核了,提前告诉mysql表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,mysql不允许你插入。
🌸🌸MySQL之表的约束大概就讲到这里啦,博主后续会继续更新更多Qt的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!如有小伙伴需要Qt的安装包可以私信我,你们的支持是博主坚持创作的动力!💪💪



