【MySQL】数据类型

前言

我们前面对库和表的操作介绍了,但是我们在前面演示的时候对字段的类型不是很理解,所以这一期我们来介绍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的人和打篮球的人

相关推荐
我有医保我先冲1 小时前
SQL复杂查询与性能优化:医药行业ERP系统实战指南
数据库·sql·性能优化
快来卷java2 小时前
MySQL篇(一):慢查询定位及索引、B树相关知识详解
java·数据结构·b树·mysql·adb
阳光_你好2 小时前
详细说明Qt 中共享内存方法: QSharedMemory 对象
开发语言·数据库·qt
喝醉酒的小白3 小时前
MySQL响应慢是否由堵塞或死锁引起?
数据库
Pasregret3 小时前
04-深入解析 Spring 事务管理原理及源码
java·数据库·后端·spring·oracle
jnrjian3 小时前
归档重做日志archived log (明显) 比redo log重做日志文件小
数据库·oracle
TDengine (老段)4 小时前
TDengine 中的命名与边界
大数据·数据库·物联网·oracle·时序数据库·tdengine·iotdb
谁家有个大人4 小时前
MYSQL中对行与列的操作
数据库·mysql
0000ysl5 小时前
数据库基础-函数&约束
数据库
JavaPub-rodert5 小时前
Etcd用的是Raft算法
数据库·github·etcd·raft