
目录
- 一、数据类型分类
- 二、数值类型
-
- [2.1 整数类型(这里以tinyint统一进行讲解)](#2.1 整数类型(这里以tinyint统一进行讲解))
- [2.2 bit类型](#2.2 bit类型)
- [2.3 浮点数类型](#2.3 浮点数类型)
-
- [2.3.1 float类型(double类型使用方法基本一致)](#2.3.1 float类型(double类型使用方法基本一致))
- [2.3.2 decimal类型](#2.3.2 decimal类型)
- 三、字符串类型
-
- [3.1 char类型](#3.1 char类型)
- [3.2 varchar类型](#3.2 varchar类型)
- [3.3 4.3.3 char和varchar比较](#3.3 4.3.3 char和varchar比较)
- 四、日期和时间类型
- 五、enum类型和set类型
- 结尾
一、数据类型分类

二、数值类型
2.1 整数类型(这里以tinyint统一进行讲解)
下面这张图片中,是各个整数类型能够存储数据的范围,默认情况下都是有符号整数,若是想要定义为无符号整数,则需要在类型后面添加unsigned。整数类型除了大小不一样外,其他的使用方式基本一致,这里就以tinyint进行统一讲解。MySQL中设计了多种整数类型,这是为了兼顾实际应用场景的需求以及数据存储空间的效率。

在下图中,我创建了一个表t1,t1表中只有一个num字段并且数据类型为tinyint,有符号的tinyint类型的取值范围为-128~127,当我向表中插入一些取值范围内的数字时,就显示了插入成功,而插入一些超过数据范围的数据时,它就报错显示数据超过范围。
上面我们使用了有符号类型进行测试,下面我们使用无符号类型进行测试,在下图中,我创建了一个表t2,t2中只有一个字段num并且为tinyint unsigned类型,它的取值范围为0~255,当我向表中插入一些取值范围内的数字时,就显示了插入成功,而插入一些超过数据范围的数据时,它就报错显示数据超过范围。

之前我们在学习C/C++的时候,当存储的数据超过了数据类型的存储范围时,编译器并不会报错,而是会发生截断或隐式类型转换。
而在MySQL中,当我们向特定的类型中插入了非法的数据,MySQL会直接拦截我们,不让我们进行对应的操作。
因为如果MySQL也向C/C++一样发生截断,则用户就无法相信MySQL的数据,到底是合法数据还是非法数据发生了截断。
当我们知道MySQL会拦截用户插入非法数据,反过来我们就知道了MySQL中存储的一定就是合法的数据。
所以MySQL中的数据类型本身就是一种约束,约束会在后面的文章中详细讲解,这里就简单讲一下。用户想要插入数据,MySQL会拦截用户插入非法数据,就使得用户需要尽可能的保证数据是合法的,所以约束顾名思义就是约束用户。
2.2 bit类型

在下图中,我创建了一个表t3,t3中有两个字段num和gender,gender为bit类型并且设置为1位,所以它的取值范围为0~1,根据下面的测试来看也确实如此,超过了这个范围的数据是无法被插入的。MySQL8.0版本后,默认是以十六进制的方式来显示bit类型的。

在下图中,我测试了bit类型的默认值和最大值,当bit类型没有设置位数时,则位数默认为1,而bit类型的位数最大为64,当用户想要操作bit类型的位数超过64时,MySQL会对用户的操作进行拦截。
2.3 浮点数类型
2.3.1 float类型(double类型使用方法基本一致)
double类型使用方法与float类型的使用方式基本一致,不同的是double类型存储数据的精度比float的精度要高。
在下图中,我创建了一个表t5,t5包含了两个字段num和salary,其中salary的数据类型类float(4,2),float(4,2)表示的范围是-99.99 ~ 99.99。当我向表中插入一些取值范围内的数字时,就显示了插入成功,而插入一些超过数据范围的数据时,它就报错显示数据超过范围。值得注意的是,在下面我插入了一次100.0,它的位数只有4位,但还是被MySQL拦截了,这是因为如果用户插入是数据小数位数不足时,MySQL会将数据的小数位数补齐。

这里我再测试一下,如果数据的小数位数超过了设置的位数会怎么样,下面我插入了一些小数位数超过设置位数的数据,但是发现其中有一部分被拦截了,有一部分则插入成功了,并且插入成功的数据是按照小数位数超过的部分进行四舍五入进行存储的,为什么有些数据插入失败了呢?这是因为这些数据进行四舍五入后超过了数据的存储范围,这样的数据在被插入的时候就会被拦截。
同样float类型默认为有符号类型,这里我再测试一下无符号类型的float类型的取值范围是多少,下面我创建了一个表t6,其中有一个字段为salary并且数据类型为无符号的float类型,下面我插入了一些数据,发现无符号的float类型同样是支持四舍五入的,然后数据的上限同样不能超过99.99,并且不能插入负数了,这时候我们就知道了无符号类型并没有扩大数据的存储范围,甚至在原来的有符号的float类型上,将数据范围中负数的那一半直接砍掉了。

这里我们修改表中的salary的数据类型,使float能够存储的范围扩大,然后再向表t6中插入一些数据,我们发现当数据很大,或数据的小数点位数很多时,float存储的数据就会发生精度损失。

2.3.2 decimal类型

decimal类型的使用方式与float类型的方式基本一致,这里就不过多讲述了。
- decimal(4,2) 表示的范围是 -99.99 ~ 99.99
- decimal(4,2) unsigned 表示的范围 0 ~ 99.99
decimal类型与FLOAT类型最大的不同就是因为存储方式不同导致的存储数据的精度不同。
在下图中,我创建了一个表t7,t7中有两个字段fnum和dnum,一个为float类型,一个为decimal类型,但两者的长度和小数位数是一致的,当我想两个类型中插入了相同的数字时,得到的结果是decimal类型保存的数据与存入的数据一模一样,而float类型保存的数据与存入的数据已经有很大的出入了。
所以如果要保存的小数精度要求较高,更推荐使用decimal类型。
三、字符串类型
3.1 char类型

cpp
char(size): 固定长度字符串,size是可以存储的长度,单位为字符,最大长度值可以为255
在下图中,我创建了一个表t8,t8中有一个字段name,它的数据类型为char并且它的能存储的字符串最长为2个字符,当我想表中插入3个字符时,MySQL确实拦截我了,但是在UTF8中,一个中文字符是需要占3个字节的,而这里插入一个中文字符却正常插入了,这是因为size的单位为字符而非字节 ,我们之前学习C/C++的时候,一个字符就是一个字节,而在MySQL中,一个字符就是一个字符,可以是中文字符也可以是英文字符。
char类型的最大长度确实为255,当想要更长时,MySQL就会拦截我们的操作。

3.2 varchar类型

cpp
varchar(size): 可变长度字符串,size表示字符长度,最大长度65535个字节
在下图中,我创建了一个表t9,t9中有一个字段name,它的数据类型为varchar(2)并且它的能存储的字符串最长为2个字符,当我想表中插入3个字符时,MySQL确实拦截我了,同样这是的size的单位为字符而非字节,就目前来看char类型和varchar类型使用起来是一样的。

下面我测试了varchar的最大字符长度,我先使用了最大字节长度进行了测试,然后MySQL报错,告诉我最大字符长度是16383。

关于varchar(size),size到底是多大,和表的编码密切相关:
varchar字节长度可以指定为0到65535之间的值,但是有1 - 3 个字节用于记录数据大小 ,所以说有效字节数是65532。
- 当我们的表的编码是utf8mb4时,varchar(n)的参数n最大值是65532/4=16383 [ 因为utf8mb4中,一个字符占用4个字节 ]
- 当我们的表的编码是utf8时,varchar(n)的参数n最大值是65532/3=21844 [ 因为utf8中,一个字符占用3个字节 ]
- 如果编码是gbk,varchar(n)的参数n最大是65532/2=32766 [ 因为gbk中,一个字符占用2字节 ]
3.3 4.3.3 char和varchar比较

如何选择定长或变长字符串?
- 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号
- 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
- 定长的磁盘空间比较浪费,但是效率高。
- 变长的磁盘空间比较节省,但是效率低。
- 定长的意义是,直接开辟好对应的空间
- 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
四、日期和时间类型
常用的日期有如下三个:
- date :日期 ,格式
'yyyy-mm-dd'
,占用三字节 - datetime :时间日期 ,格式
'yyyy-mm-dd HH:ii:ss'
表示范围从 1000 到 9999 ,占用八字节 - timestamp :时间戳 ,从1970年1月1日00:00:00 开始的,格式
yyyy-mm-dd HH:ii:ss
和 datetime 完全一致,占用四字节
下面我创建了一个表t10,将这3个类型都使用一下,由于MySQL8.0中timestamp无法自动生成时间,这里我就自己填充了一下。

五、enum类型和set类型

cpp
enum:枚举,"单选"类型;
enum('选项1','选项2','选项3',...);
该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值,实际上我们还可以通过数字的方式插入对应的枚举值,因为这些选项的每个选项值依次对应如下数字:1、2、3、...,所以最终插入枚举值有两种方式,直接添加选项中的值或是值对应的数字。
cpp
set:集合,"多选"类型;
set('选项值1','选项值2','选项值3', ...);
该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值。当我们向集合内插入数字时,这个数字代表的是位图,从低到高依次是集合从左向右的内容。
下面我创建了一个表vates(调查表),表中字段gender为性别,使用枚举有男、女两个选项,表中字段hobby为爱好,使用集合有五个选项。
下面我先测试了枚举,插入数据时,枚举值要么是数字要么是选项里的值,若是数字超过范围或是枚举值不是选项中的一个,则会被拦截,插入失败。
下面测试集合,在我进行插入时,发现集合确实能插入多个值,并且还可以使用数字来替代,举个例子3的位图就是00011,对应集合的选项就是最右边两个,也就是篮球和羽毛球。
查询会在后面的文章中详细讲解,当我们想查询爱好中有篮球的时候,使用下面这种方式来查时,发现查询出来的爱好是严格匹配爱好只有篮球的,下面我们就要学习一个函数。
集合查询使用find_ in_ set函数:
find_in_set(sub,str_list)
:如果 sub 在 str_list 中,则返回下标;如果不在,返回0;str_list 用逗号分隔的字符串。
我们发现使用这个函数后就确实可以找到爱好中有篮球的所有信息了。
若我们想找到爱好中有篮球和乒乓球的所有信息,就可以使用and将两个条件连接起来,这里只是简单的讲一下,后面会详细的讲述查询。
结尾
如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹
