【MySQL】表的约束

目录

零、前言

表中一定要有各种约束,通过约束来让用户未来插入的数据是符合要求的。约束的本质就是通过计算反过来要求用户插入正确的数据。所以站在MySQL的角度上来看,凡是插入进来的数据,一定是符合条件约束的。

约束最终的目的就是保证数据的完整性和可预期性,所以MySQL中需要更多的约束。


一、空属性

  • 两个值:null(默认的)和not null(不为空)
  • 数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与运算。

下面我创建了一个表class,class有三个字段,class_name和class_room不能为null,而other默认可以为null,所以在下面插入数据的时候,我先尝试每个字段都填有数据,发现可以插入成功。然后再插入数据时,只填写字段class_name和class_room的对应数据,发现同样可以插入成功,这是因为字段other默认可以为null,然后我再插入时,只填写class_name对应的数据时,发现出错了,并告诉我字段class_name没有默认值。最后我再插入数据时,只填写字段class_name和class_room的对应数据,但是class_room对应的数据填写为null,这次它又报错,并告诉我插入到字段class_room的数据不能为null。

所以当我们给一个字段添加了非空约束,用户想向当前字段插入null值,都会被MySQL拦截,这就是非空约束。


二、默认值

默认值:某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值。

下面我创建了一个表t1,t1包含三个字段name,age和sex,其中name没有默认值且不能为null,age默认为18且可以为空,sex默认为男且不能为空。

这里我先测试字段name,字段name没有默认值且不能为null。首先我先指定所有字段插入有效数据,插入成功,然后我再指定所有字段插入数据,但只有字段name的数据为null,这时候MySQL就拦截我的操作并告诉我字段name处的数据不允许为null,最后我只指定字段age和sex插入有效数据并且我不想给字段name插入数据,这时候MySQL就拦截我的操作并告诉我字段name没有默认值。

这里我再测试字段age,字段age默认为18且可以为空 。首先我先指定所有字段插入有效数据,插入成功,然后我只指定字段name和sex插入有效数据并且我不想给age字段插入数据,还是插入成功并且age使用的是默认值18,最后我再指定所有字段插入数据,但只有字段age的数据为null,最终还是插入成功。

这里我最后测试字段sex,字段sex默认为男且不能为空。首先我先指定所有字段插入有效数据,插入成功,我只指定字段name和age插入有效数据并且我不想给sex字段插入数据,还是插入成功并且sex使用的是默认值男,最后我再指定所有字段插入数据,但只有字段sex的数据为null,这时候MySQL就拦截我的操作并告诉我字段sex处的数据不允许为null。

小结:

从这里我们就可以得出一个结论了,not nulldefault 并不是冲突,并且两者还是互相补充的。

  • 对于 not null 来说,用户的数据会被分为两类:null 和 合法数据,not null 约束的就是用户想插入数据并且插入的数据不能为null
  • 对于 default 来说,用户被分为两类:想输入的和不想输入的,default 使得想输入的用户可以输入自己的数据,使得不想输入数据的用户使用默认值。当用户没有给字段设置default选项并不想输入数据时,MySQL就会对该操作进行拦截。

注意:MySQL中允许 not null 和 default 同时出现,但是 not null 和 defalut 一般不需要同时出现,因为 default 本身有默认值,不会为空。


我们之前在建表时,没有给字段设置default和not null属性,但是用户不想插入数据的时候,它默认给他插入的值是null。这是MySQL的默认表定义行为。


三、列描述

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或数据库管理员来进行了解。

通过desc查看不到描述信息,通过show可以看到描述信息。


四、zerofill

我们知道很多类型后面都有(),并且我们也知道其中数字的意义,实际上int类型后面也可以带(),这里我们就来讲述一下int类型后面数字的意义是什么,在MySQL8.0.17版本后,默认就不显示()和里面的数字了,只有带上 zerofill 选项才会显示。

实际上int后面的数字就是int的显示宽度,当带上了zerofill选项后,用户查找表中的信息时,存储数据的宽度小于设置的显示宽度时,就会在数据的前面补充0,直到与设定的显示宽度相同,zerofill并不影响数据存储,它只影响后面的格式化显示。

下面我将表中字段num2的显示宽度调整为5,再向表中插入一些数据,然后就可以发现,当存储的数据的宽度小于显示宽度,就会在显示时在数据前面添加0,而当存储的数据的宽度等于或大于显示宽度,显示时该怎么显示就怎么显示。


五、主键

主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键;主键所在的列通常是整数类型。

下面我创建了一个t5,t5包含两个字段id和name,其中id为主键,当我查看创建表t5的命令时,发现MySQL对我的命令进行了调整,这也是一种给字段添加主键的方式,并且当一个字段为主键时,MySQL会默认给这个字段添加非空约束。

当我向表中插入一些数据的时候,当id不重复时,都可以成功插入,当重复时,MySQL就会拦截这一操作,并告诉我主键冲突了。

当一个表中含有主键时,还可以删除主键。

cpp 复制代码
ALTER TABLE 表名 DROP PRIMARY KEY;

下面我就删除了表t5的主键,当我再次查看创建表的命令时,就没有了主键的相关的内容了,并且当表中含有相同的id时,同样可以插入了。

当表创建好以后但是没有主键的时候,可以再次追加主键

下面我向表t5追加主键,但是MySQL拦截了我的操作并提醒我字段id这个列中有重复的数据,当我删除掉其中一行数据以后,再次追加主键就成功了,之后想要插入id相同的数据,MySQL就会对该操作进行拦截。

所以主键最好是在创建表的时候就带上,或是刚刚创建表后追加主键,不要已经使用了一段时间后再追加。

复合主键:一个表中只允许有一个主键,但是不代表主键只能是一列。在创建表的时候,在所有字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键。

cpp 复制代码
ALTER TABLE 表名 ADD PRIMARY KEY (字段列表);

在大学中就有这样的应用场景,大学生在选课时,可以一个人选多门课,也可以多个人选同一门课,但是不允许一个人多次选择同一门课。

下面我创建一个表t6,t6中有两个字段id和course,这两个字段合起来为一个复合主键。当我使用desc命令查看表t6时,发现两个字段都是pri,这并不代表有两个主键,而是两个字段合起来是主键,并且MySQL默认给主键添加了非空约束,当我向表中插入相同数据的,MySQL会对我的操作进行拦截。


六、自增长

auto_increment :当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值。通常和主键搭配使用,作为逻辑主键

自增长的特点:

  • 任何一个字段要做自增长,前提是本身是一个索引(key一栏有值)
  • 自增长字段必须是整数
  • 一张表最多只能有一个自增长

下面我创建了一张表t7,t7中有两个字段,其中字段id为主键并且自增长,下面我向表中插入了一些数据,并且我不指定id的值,发现id默认是从1开始的,当我再插入一个数据并指定id为100,然后再插入数据并且不指定id的值,发现后面的id是从我指的的id后面开始增长。

当用户创建包含自增长字段的表时,如果该字段的起始值未指定,则默认从1开始自动递增。后续插入数据时,若用户为该字段指定了值,系统将基于此值加1后保存。


七、唯一键

一张表中有往往有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键,唯一键就可以解决表中有多个字段需要唯一性约束的问题

唯一键的本质和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较。

举个例子:在大学中中,每个人都有身份证号码,每个人都有自己的学号,但不一定每一个人都有电话号码,身份证号码是每个人都不一样的,学号也是每个人都不一样的,电话号码也是每个人都不一样的,一个大学生的身份证号码和学号和其他人的都不一样,辅导员找学生可以使用身份证号码,也可以使用学号,在大学中通常就是使用学号来查找对应的学生,但并不是说身份证号码就不能找到这个学生,所以我们可以选择其中身份证号码和学号其中一个作为主键,但不意味着大学生其他的属性不需要维护唯一性,所以需要唯一键来维护大学生的其他需要唯一性的属性。

下面我创建了一个表student,student中有3个字段id、num和telephone,其中id为主键,其他两个为唯一键,将表创建出来后,查看详细信息,我们发现了唯一键默认可以为空。

下面向表student中插入一些数据,通过下面插入数据的信息来看,当插入数据中对应唯一键上的列数据与表中的冲突相同时,MySQL会对该操作进行拦截,但是当我将对应的数据修改为NULL时,却插入成功了。

主键 VS 唯一键

主键通常用来标定一行数据在整表中的唯一性,唯一键是为了让插入的列值与表中其他的列值不要冲突。一个表是用来描述对象的各种属性列的,这时候我们可以选择这个属性列作为主键,但不意味着对象其他的属性不需要维护唯一性,一个属性列是主键,仅仅是因为我们选择它为主键,并不是其他属性不能作为主键。


八、外键

外键用于定义主表和从表 之间的关系:外键约束主要定义在从表上,主表则必须是有主键约束或唯一键约束。当定义外键后,要求外键列数据必须在主表的主键列存在或为null。

cpp 复制代码
foreign key (字段名) references 主表(列)

例子:

首先这里我先创建主表,再插入一些班级信息,一般来说是先有班级后才有学生。

然后再创建学生表,并且插入一些学生消息,注意这里现在并没有使用外键约束。当我插入王中王这位同学时,它的班级号为3,虽然说插入成功了,但班级表中并没有这个班级。

最后我想删除火箭班,按理来说班级中还有人,就不应该能够删除这个班,所以目前来看,学生表和班级表只有外键之名,没有外键之实,外键=关系+约束


下面我重新创建两张表,让两张表形成关联关系,并使用外键约束,然后再插入一些数据。

这里我先向班级表中插入一些数据,再向学生表中插入一些数据,最后再删除班级表中的一些数据。

当我插入王中王这位同学时,它的班级号为3,但显然班级表中并没有3号这个班级,又由于外键约束的存在,所以MySQL将我的插入操作拦截了。

这里我想从班级表中删除火箭班,但是此时学生表中还有同学是属于这个班的,所以又因为外键约束的原因,MySQL将我的操作拦截了,只有学生表中没有属于这个班级的学生时,MySQL才会运行我删除这个班级。

小结:

建立外键的本质其实就是把相关性交给MySQL去审核了,提前告诉MySQL表之间的约束关系,那么当用户插入不符合业务逻辑的数据的时候,MySQL不允许你插入。


结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。

希望大家以后也能和我一起进步!!🌹🌹

如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

相关推荐
zhglhy2 小时前
mysql与redis的日志策略
数据库·redis·mysql
小画家~2 小时前
第三:go 操作mysql
开发语言·mysql·golang
tpoog3 小时前
MySQL:数据库基础
linux·c语言·开发语言·数据库·redis·mysql
傻啦嘿哟3 小时前
python中time模块的常用方法及应用
开发语言·数据库·python
Lightning_20174 小时前
软考中级-数据库-5.3-Internet基础知识
linux·网络·数据库·职场和发展
车载诊断技术5 小时前
电子电气架构 --- 汽车面对软件怎么“破局“?
数据库·人工智能·架构·汽车·电子电器框架·汽车面对软件怎么破局·智能电动汽车概述
橙子家5 小时前
Redis 持久化机制简介【Redis 系列之三】
数据库
XU磊2606 小时前
告别 ResultSet 的烦恼:使用 Apache DBUtils 和 ArrayList 优化数据管理
java·数据库·mysql·apache·database
master-dragon6 小时前
缓存及其问题解决
数据库·缓存