前言
我们前面对库和表的操作介绍了,但是我们在前面演示的时候对字段的类型不是很理解,所以这一期我们来介绍MySQL的数据类型。
目录
[2.1 tinyint类型](#2.1 tinyint类型)
[2.2 bit类型](#2.2 bit类型)
[2.3 小数类型](#2.3 小数类型)
[3.1 char类型](#3.1 char类型)
[3.2 varchar类型](#3.2 varchar类型)
[3.3 char 和 varchar 的对比](#3.3 char 和 varchar 的对比)
[五、enum 和 set类型](#五、enum 和 set类型)
[5.1 enum 和 set 类型的区别](#5.1 enum 和 set 类型的区别)
[5.2 enum 和 set 的使用案例](#5.2 enum 和 set 的使用案例)
[5.3 enum 和 set 的查询](#5.3 enum 和 set 的查询)
[5.4 使用 find_in_set函数进行集合查询](#5.4 使用 find_in_set函数进行集合查询)
一、数据类型的分类
数值类型

二进制文本类型

时间日期类型

字符串类型

二、数值类型
数值类型这里我们拿几个来来举栗,其他的类似(整数类型就用tinyint说明,其他类似):
2.1 tinyint类型
tinyint 占一个字节,即范围是 [-2^8, 2^8-1]=> [-128, 127]
注意:MySQL 中整数默认是有符号的,若想使用 则使用 unsigned 说明

我们先来插入tinyint 的范围内的:

我们直接来测试边界情况,顺便输出一个结论:

这里我们输出的结论就是:
1、如果向MySQL特定类型的字段中插入不合法的数据,MySQL一般会将本次操作直接拦截。反过来讲,能被插入到MySQL中的数据一定是合法的。
2、在MySQL中,数据类型本身也是一种约束,这种约束是约束使用者的,让程序员在使用的过程中尽可能的正确操作。
下面我们来使用一下 无符号类型:
无符号 tinyint 类型的取值范围是 [0, 2^8-1] => [0,255]

先来插入正常范围的值:

再来测试一下边界和越界报错:

2.2 bit类型
语法格式:
sql
bit[(M)]: 位字段类型。M表示每个值的位数,范围1-64,。如果M忽略则默认是 1
我们创建t3表,然后有两个字段:int类型的 id 和 bit(1)类型的gender,并向里面插入两个数据

我们查询所有,发现命名性别这里我们插入了0和1,但是看不见?
原因是,比特字段在显示时是按照ASCII码对应的值显示的!而ASCII 0和1对应的字符是不可显示的,所以看不见!
我们可以在创建它表,设置bit的M为10,然后插入a和97,显示的就是a:

可是我现在就想看到t3表中他确实被插入了如何查?答案是转为16进制:

如果我们只有像0/1这样的值,我们可以定义bit(1),这样可以节约空间!
2.3 小数类型
小数类型有 float、doule、decimal其中 float 和 double 差不多或者范围比前者大,我们这里介绍一个 float,而 decimal 与前者的差别是 精度问题。
• float
语法格式:
sql
float[(m,d)] [unsigned]:M指定浮点数整体的位数,d指定小数位数,占空间 4 个字节。
有符号 小数:float(4,2) 表示的是整个浮点数的位数是4位,小数部分是两位,所以其范围是 [-99.99,99.99]
注意: MySQL在保存值时会进行四舍五入,也就是float并不是完全和其他类型一样严格超过就报错的,如上的 **[-99.994... , 99.994...]**以内的都可以!


无符号 小数:float(4,2) unsigned 表述小数的证入体位数是4位,小数部分是两位,取值范围是**[0, 99.994...]**。


float的精度一定情况下超过一定的位数会有损失,例如:

因为float和double有精度的损失,所以就有了decimal 类型了!
• decimal
语法格式:
sql
decimal(m, d) [unsigned] : m表示浮点数整体的长度,d表示小数本部分的位数
• decimal(5,2) 表示的是整体小数位是5位,2位是小数部分。取值范围:[-999.994.., 999.994...]
• decimal(5,2) unsigned 取值范围:[0, 999.994...]
decimal 和 float 很像但是有区别,float和decimal的表示精度不一样:
我创一张张表添加两个字段分别是float(10,8)和decimal(10,8),然后插入一样的而数据,来看一下区别:

我们明显的看到float的精度是存在问题的,而decimal的精度是准确的。因此,如果我们希望某个数据表示精度更好,则选择decimal。
说明:
1、float 表示的精度大约是7位左右。
2、decimal类型字段的整数部分最大位m是65 ,小数部分最大位d是30。
3、float 和 decimal 如果d被省略则默认是0,m则默认是10。
三、字符串类型
3.1 char类型
语法格式:
sql
char(L): 固定长度字符串,L是可以存储的长度, 单位为字符,最大长度值为 255
注意 :这里的单位是 字符!字符包括常见的字符也包含汉字!
我们创建一张表t9里面设置一个char(2)的字段

关于int(N)这个N有点特殊,他和索引有关系,我们到后面的索引章节在介绍!
我们分别插入不同的字符验证一下:

我们发现是只要在L字符(这里是2)以内都是可以插入成功的!下面我们再来试一下,越界测试:

一旦越界还是和去哦他类型一样,MySQL会直接拦截掉!
3.2 varchar类型
语法格式:
sql
varchar(L):可变长字符串,L表示字符的长度, 最大长度范围是65535字节
注意 :L是字符 个数,而varchar的最大存储范围是65535字节
我们创建一张表t10,里面创建一个varchar(6)的name字段

然后插入不同的字符:

varchar的取值范围是[0,65535]字节,但是有1-3个字节用于记录数据大小,所以有字节数是 65532。
关于varchar(L),L字符个数到底是多大,这个L值和表的编码有关系:
• 当表的编码是utf8时,varchar(L)的L最大值是 65532 / 3 = 21844个字符;(因为一个字符占三个字节)
• 当表的编码是gbk时,varchar(L)的L最大值是 65532 / 2 = 32766个字符;(因为一个子符占两个字节)

gbk编码同理这里就不验证了,可以字节在创建表时指定编码集和校验集,验证即可!
3.3 char 和 varchar 的对比

• char 和 varchar 的区别
1、char类型可存储的字符上限是 255个,而varchar的存储的字符上限受表的编码格式的影响。
2、char(L)在定义后,会一次开辟好L个字符的空间,而varchar(L)则是以L为上限的情况下,用多少开辟多少。(char类似于字符数组,varchar类似于string)
• char 和 varchar 的优缺点
1、char是定长的,因此会比较浪费磁盘空间,但是效率高(能直接访问定长的空间)。
2、varchar是变长的,因此会比较节省磁盘空间,但是效率低(需要维护字符串)。
• char 和 varchar 如何选择?
1、如果数据确定长度都一样,就使用定长 char, 比如:身份证、手机号、md5加密
2、如果数据长度会变化,就使用 varchar, 比如:名字、地址等
四、日期和时间类型
常用的日期类型有如下的三个:
• date :日期 'yyyy-mm-dd' 占三个字节
• datetime :时间日期格式 'yyyy-mm-dd HH:ii:ss'表示范围从1000到9999,占用8个字节
• timestamp:时间戳,1970年开始 'yyyy-mm-dd HH:ii:ss'和datetime的格式完全一致,占用4字节
我们创建一张表date_tb,里面的三个字段分别对应上面的三个类型:

注意 :时间戳这个类型的字段,我们不需要手动的插入或者更新,在每次对其他字段进行更新时会自动的更新!

我们更新一下,看看时间戳会自动改变:

五、enum 和 set类型
5.1 enum 和 set 类型的区别
enum 枚举 (单选) 类型:在定义 enum 字段时需要提供若干个选项的值,在设置 enum字段值时只允许选取其中的一个值。
bash
enum('选项1', '选项2', '选项3', ..., '选项n')
set 集合 (多选) 类型:在定义 set 字段时需要提供若干个选项的值,在设置 set 字段值时可以选取其中的一个或多个值。
bash
set('选项值1', '选项值2', '选项值3', ..., '选项值n')
5.2 enum 和 set 的使用案例
有一个调查表 votes ,需要调查人的喜好和性别,爱好,比如(唱、跳、rap、打篮球、写代码)可多选!性别(男,女)单选
然后插入一些数据:

这里我们插入了一些简单的,爱好,也可以插入多个爱好:

当然除了上述的直接在插入时指定选项外,还可以使用数字指定:
• enum 的每一个枚举选项可以用一个数字表示,第几个"下标",比如上面的男就是1,女就是2!
• set 的每一个选项使用的一个位图的结构组织的,比如上面的5个选项,就是11111,比如想要前三个就是00111就是7

注意 :虽然通过数字设置 enum 和 set 值很方便,但还是不推荐通过数字设置 enum 和 set 值,因为这样会导致可读性变差的情况。
5.3 enum 和 set 的查询
MySQL 也支持通过 enum 和 set 中的值进行查找。
1、使用enum进行查找

当然也是可以使用下标的:

2、使用set进行查找

可是我现在想达到的,查询所有包含某个选项的数据条目呢?那就得使用find_in_set函数了!
5.4 使用 find_in_set函数进行集合查询
find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回 0 ; str_list 用逗号分隔的字符串。
先来举个例子:

所以,我们可以借助该函数对上述的set集合进行查询:我们这里查询所有rap的人

查询所有rap的人和打篮球的人
