【MySQL】表的约束(上)

文章目录

  • [1. 空属性(非空约束)](#1. 空属性(非空约束))
  • [2. 默认值(default约束)](#2. 默认值(default约束))
  • [3. 非空约束与default约束对比](#3. 非空约束与default约束对比)
  • [补充1: 列描述(comment)](#补充1: 列描述(comment))
  • 补充2:zerofill(0填充)

什么是表的约束呢?我们先来简单的理解一下

如果我们往一个文件里面写入数据,我可以随便写,想写什么写什么,这就是没有约束。
而数据库中建立的表,我们往里面插入数据,是有约束,即不能随便想插入什么就插入什么。
如何理解?
你可以把数据库的表想象成一张 Excel 表格,用来记录信息,比如一个"员工信息表"。
表的"约束",就是你在设计这张表格时,提前定好的 "填写规则 "。它的目的是为了保证你以后往表里添加或修改数据时,数据是可预期的,完整的。比如有一列是性别,那你就只能填男和女,不能随便填别的,比如填成了年龄,身高体重等。填别的就会被拦截。
所以,表中就有各种的约束,通过约束,使得我们未来插入表中的数据是完整的,符合预期的。通过约束,倒逼使用者,插入正确的数据。反过来,站在MySQL的视角,凡是插入进来的数据,都是符合约束的。
约束的最终目标:保证数据的完整性和可预期性。

简单总结一下:

表的约束(Table Constraints)是关系型数据库中用于强制实施数据完整性规则(Data Integrity Rules)的机制。它们是在表级别定义的规则,用于限制表中数据的值,确保数据库中的数据满足预定义的业务逻辑和一致性要求。
(等我们把表的约束讲完之后大家可以回过头来再理解这个概念)

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

null/not null,default, comment, zerofill,primary

key,auto_increment,unique key 。

1. 空属性(非空约束)

两个值:null(空---默认运行为空)和not null(非空)

如果某一列在将来插入时不允许为空,即必须插入有效值(不允许插入空),则可以将这一列的属性带上not null,若允许为空,则属性带上null,不设置,默认允许为空

案例:创建一个班级表,包含两列,班级名和班级所在的教室,两个字段都不允许为空,即一个班级一定有对应的教室,一个教室一定被分配给特定的班级。

建表:
create table class( class_name varchar(20) not null, class_room varchar(20) not null, other varchar(20) );


即前两列我们必须插入有效数据(不能插入空) ,第三列可以插入空或者不插入(默认值为空),当然如果插入了那就放我们插入的值
试一下

前两列我们都插入了数据(当然也必须插入,因为不允许为空),第三列我们第二次没有插入,但我们看到默认填充了NULL,第三列也允许为空,这没毛病。
如果我想只插入班级名,后两列都不插可以嘛

当然不行,报错说class_room这一列没有默认值,因为默认为空,但我们指定了这一列不允许为空,所以就没有默认值了.
如果我显式地给他插入一个NULL,当然也不行

因为我们约束了它不允许为空,这就是非空约束

2. 默认值(default约束)

默认值:

当我们在向表中插入数据时,如果某一列我们没有插入,则他会填充默认值。
就有点类似C++中的缺省参数,如果我们自己传了,那就使用我们传的参数,如果没传,那就使用缺省参数。
如果某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,将其作为默认值,在需要真实数据的时候,用户可以选择性的使用默认值。
比如有一个程序员的交流网站,用户注册时,性别这一栏就可以将默认值设为男,如果用户自己输入了,那就以用户输入的为准,如果没有,那就默认性别为男。

下面我们通过案例来理解一下:

建个表
create table t11( name varchar(20) not null, age tinyint unsigned default 18, gender char(1) default '男' );

第一列name,类型为变长字符串,长度20,同时我们约束不能为空(一定要插入非空值);第二列age,类型为tinyint,我们约束了默认值为18;第三列gender,类型为长度为1的定长字符串,约束默认值为男。
插入一些数据观察一下

我们发现,对于指定了默认值的列,如果我们自己插入了数据,就用我们自己插入的,如果我们没有自己插入,则用默认值。

3. 非空约束与default约束对比

再来看这样一张表:


与上面表t11的唯一区别就是gender这一列我们指定了默认值为男,同时还约束了非空。

那大家想,指定了默认值之后,如果我们自己插入数据了,那就用插入的,如果没有也有默认值,所以按理说就不会为空了。那not null是不是有没有都一样啊?

我们来验证一下:

先来关注一下第一列

这两条插入语句都不行,来分析一下:
第一条插入,我们给name列插入了空,但是建表时约束了not null,所以不能为空(报错也是这样说的)
第二条插入,我们没有给name列插入数据,报错说name列没有默认值。此时起作用的约束不是空属性,而是默认值约束。

再来观察第二列:

第二列设置了默认值,但没有约束非空,所以第一次我们不给第二列插入值,用了默认值18;第二次,我们插入了null,发现可以插入,因为并没有约束非空。
再观察第三列(即约束了非空,又指定了默认值):

第一次不插入用了默认值男,第二次插入空失败,因为约束了非空。

所以,回答上面的问题,第三列即设定了默认值,又指明了非空,那not null是不是有没有都一样呢?

显然答案不是的。
上面我们说:【指定了默认值之后,如果我们自己插入数据了,那就用插入的,如果没有也有默认值,所以按理说就不会为空了,那not null是不是有没有都一样啊?】
但是我们如果没有not null,我们还可以自己插入空,如果有,则不能插入空。

所以:

not null 和 default 并不冲突,而是互相补充的。
not null的约束什么时候起作用呢?
是当用户自己显式插入数据的时候 ,插入的值只可能是空/非空的合法数据,但若进行了非空约束,则不能插入null。
default呢?
用户忽略这一列的时候 ,此时如果设置了默认值,则自动填充默认值,如果没有设置,直接报错(即没有默认值的时候不能省略)。
不过实际应用中not null和defalut一般不需要同时出现。

下面再来做一个实验:

再建个表

有两列,name和age,类型和上面是一样的,不过这次我们没有添加任何显式的约束,非空和默认值
然后我们来插入一些数据

我们发现,插入空是可以的,因为没有非空约束;
而且任意一列插入的时候也可以省略,但是我们并没有指定默认值啊(其实我们之前就这样做过)。
不过我们看到可以省略,省略的话默认填充了null。
什么原因呢?

如图所示,原因在于,建表时如果我们自己没有手动指明默认值,MySQL会自动加上DEFAULT NULL,指明其默认值为null。
那如果我建表时只加了not null约束,没有加默认值,MySQL还会自动加DEFAULT NULL嘛?
就不会了,我们上面其实已经有对应的例子验证过了。

那没有默认值,用户就一定要自己插入值,又因为有非空约束,所以一定要插入非空值,这时not null约束就起作用了。

补充1: 列描述(comment)

列描述:comment,其实没有什么约束的作用 (严格意义来说COMMENT不是一种约束),没有实际含义,专门用来描述字段(类似编程语言中的注释),会根据表创建语句保存,用来给程序员或DBA(数据库管理员)来进行了解

下面我们还是通过案例来理解一下它:

建表


三列,这次每列我都添加了comment,描述了这一列的含义。
但我们看到它在desc 查看表结构里面并没有体现
通过show create table 表名;可以看到

所以它不是给数据库看到,用来给程序员或DBA(数据库管理员)来了解相关信息的,如果通过列名不知道这一列存的是什么,可以通过comment来了解。

补充2:zerofill(0填充)

zerofill在某些资料中也不被认为是一种严格意义上的约束,很多地方说法不一:

ZEROFILL 是 MySQL 中数值数据类型(INT、DECIMAL 等)的显示修饰符

下面还是通过例子来理解:

建个表

我当前的MySQL版本是8.0.44。
如果在版本更低一点的MySQL中,你可能看到的是这样的

建表的语句,出了表名完全一样,但是我们看到int后面有个(10)
int不是4字节嘛,那这个(10)是什么意思呢?
这里的(10)表示显示宽度
虽然我当前版本的MySQL没显示,但默认显示宽度仍然是 10。只是 MySQL 8.0 进行了显示优化。
我们先来给表中插入一些数据

没有问题。
然后我们来修改一下表结构,b这一列添加上zerofill属性
alter table t15 modify b int unsigned zerofill not null;

首先,我们观察到,我给b这一列添加了zerofill之后,(10)自动显示出来了。
然后我们再来查看表中的数据

我们发现b这一列,我们之前插入的2,它的前面多了9个0
那现在总的长度就是10 了,这跟括号里面的数字是匹配的。
那再插入一组数据

200本身长度是3,所以这次前面补了7个0,总长度为10。

这就是zerofill的作用:

如果插入数据的宽度小于对应的显示宽度(不指明默认为10),则会自动填充0。这样最后这一列的所有数据显示出来就是等宽的,即使我们插入的数据长度不一。
但是要注意,这只是最后显示的结果,在MySQL中实际存储的还是2和200。
我们可以来验证一下
方法一:

方法二:

16进制,对应的就是2和200。
可以看出数据库内部存储的还是2和200,补0只是设置了zerofill属性后的一种格式化输出而已。

当然这里默认显示宽度是10,我们也可以自己指定

比如改成5

那如果我们插入数据的宽度大于这个显示长度呢?


那是什么就显示什么,也不会给你截短。

最后,再来讲一个细节:

通过上面的例子我们知道这个默认显示宽度是10 ,而上面我们列的类型是int unsigned (无符号整形),那为什么是10呢?

因为无符号整形的最大值刚好10位。
如果类型改成int(有符号)

你会发现默认宽度变成11了,为什么多1?
int的取值范围是-2147483648 到 2147483647。
所以多的1是因为负数的时候,要显示负号。

相关推荐
_李小白2 小时前
【Android 美颜相机】第二天:Android-GPUImage Sample模块源码解析
android·数码相机
云和数据.ChenGuang2 小时前
运维故障之MySQL 连接授权错误
运维·数据库·人工智能·mysql
2501_915909062 小时前
Charles 抓不到包怎么办?iOS 调试过程中如何判断请求路径
android·ios·小程序·https·uni-app·iphone·webview
2501_916007472 小时前
iOS和iPadOS文件管理系统全面解析与使用指南
android·ios·小程序·https·uni-app·iphone·webview
枫叶梨花2 小时前
Greenplum数据库身份证查验函数
数据库
Pocker_Spades_A2 小时前
数据库的“多模融合”——金仓
数据库
Maggie_ssss_supp3 小时前
Linux-MySQL数据类型&表操作
数据库·mysql
廋到被风吹走3 小时前
【数据库】【MySQL】高可用架构深度解析:从主从复制到自动切换
数据库·mysql·架构
IT邦德3 小时前
PostgreSQL 通过 mysql_fdw连通MySQL实战
数据库·mysql·postgresql