一文通关 MySQL 数据类型,打好高性能数据库的第一战!

🔥海棠蚀omo:个人主页
❄️个人专栏:《初识数据结构》,《C++:从入门到实践》,《Linux:从零基础到实践》,《Linux网络:从不懂到不会》,《MySQL:新手入门指南》
✨追光的人,终会光芒万丈
博主简介:

目录
前言:
在上一篇文章中,我们学习了库和表的相关操作,而在我们上一篇的讲解中,我们提到了在列名后面跟的是数据类型,但是对于MySQL中的数据类型我们现在还一知半解,那么今天这篇文章我们就来详细谈一谈MySQL中的数据类型。
那么在详细讲解每种数据类型之前,我们先来看一下MySQL中都有哪些数据类型:

上面这幅图中就展示了MySQL中常见的数据类型,可以看到MySQL中对于数据类型是由不同的分类的,那么下面我们就详细讲解上面的各种数据类型。
一.数值类型
在上面的表中,数值类型是有很多种的,下面我们来看这张图:

我们将其中和int类型相关的各种类型给提取了出来,以及它们的取值范围,而上面这么多int类型,我们以tinyint为例,来讲int类型相关的知识。
1.1tinyint类型
那么废话不多说,我们直接来实操演示一下:

那么首先我们先创建一个表,里面就有一个属性num,类型就是tinyint,那么下面我们就像这张表中填入一些数据:

既然tinyint的范围是-128~127,上面我们就测试了一下它的极限值,发现是没有问题的,并且中间我们还插入了一些范围的值都是没有问题,那么要是插入范围之外的值呢?我们来看:

这里我们就插入了它所规定的范围之外的一些值,可以看到是插不进去的,MySQL直接就将我们拦截了下来,不让我们做对应的操作,说超出了范围。
而在上面int类型图中我们看到了在这些类型的后面跟了一个可选项[unsigned],那么我们将这个可选项加上会发生什么呢?我们来看:

那么我们再创建一个表,里面的属性依旧只有num,但是此时tinyint类型的后面跟上了unsigned,代表此时的tinyint类型是无符号的。
而从上面的图表中我们可以看到无符号的tinyint范围是0~255,那么是否真的是这个范围呢?我们来试验一下:

可以看到无符号的tinyint范围确实是0~255,不在该范围的数据我们是无法插入进去的,和上面是一样的。
虽然剩下的几种int类型我们并没有讲解,但是它们和上面讲解的tinyint并没有什么区别。
1.2bit类型

那么下面我们要讲的类型就是bit类型,我们要传入的M就是比特位的位数,上面也说了,如果我们不传M,默认就为1。
那么下面我们也是直接来通过实操来演示一下:

首先我们先来创建一个表,其中的属性a,我们将其类型设置为bit,M设置为8,那么下面我们就向这里面填入一些数值:


当我们给a插入的值为10的时候,我们发现了一个很奇怪的现象:明明我们插入了数值,但是在表中并没有显示出来我们插入的值,这是为什么呢?
答案就是bit字段在显示的时候,是按照ASCII码对应的值显示的,并不会直接显示出来,所以我们可以插入特别一点的数值来进行查看:


可以看到当我们插入65这个数值时,它所对应的的正是大写字母A,所以就显示出来了。
和上面的tinyint类型一样,如果插入的数值超出了比特位所能表示出来的最大值,也就是超出了范围,MySQL一样是会拦截我们的。
我们如果要想看到这个效果可以将M设置为1,那么它所能表达的最大值就是1,我们可以传入2来看看效果,这里就不再演示了。
二.小数类型
数值类型讲完了,下面我们就来进入小数类型。
2.1float类型

float类型就是我们所熟知的浮点数类型,该类型要传入两个参数:M和d,在上图中解释了这两个参数的作用,所以下面我们就直接来进行实验:

我们先创建一个表,表中的salary的类型就是float,我们将M设置为4,d设置为2,所以范围就是-99.99~99.99,下面我们向其中插入一些数值来看看:



那么从上面的结果中我们可以看到只要在-99.99~99.99这个范围内,插入数据是没有问题的,而只要超出这个范围,MySQL依旧会来拦截我们。
那么此时我们来思考一个问题:如果插入的数据在这个范围内,但是不符合上面的(4,2),能否插入成功呢?我们一起来看一看:

当我们小数点传了三位后,我们发现数据依旧可以插入成功,出现这种现象的原因就是:MySQL对于浮点数的要求没那么严格,像上面我们传入的三个数据,它是会进行四舍五入的!!!
那么难道只有在这个范围内要求会松一点吗?那要是在这个范围外呢?下面我们再来看一看:

当我们传入超出范围的数值时,发现有的是可以插入的,有的则不行,我们通过观察可以发现:能够成功插入的数据经过四舍五入后是99.99,并没有超出范围,但是插入失败的数据经过四舍五入后是100.00,是超出了范围的,所以MySQL就会拦截我们。
那么同时我们在上面也看到了float后面也是跟了一个可选项[unsigned],那么我们加上这个可选项来看看有什么变化:

依旧先创建一个表,不过这次我们在float的后面加上了unsigned,那么现在我们就想起中插入一些数据看看效果:

那么在上面呢我们用一些数据来进行实验,发现加了unsigned后,无法再向表中添加负数,但是正数部分的上限没有变化,也就是整个的范围变为了:0~99.99。
2.2decimal类型

decimal类型和上面我们讲的float类型非常相似,都是要传入两个参数,并且两个参数的含义也是相同的,那么它们之间的区别是什么呢?
区别就是它们两者的精度不同,decimal的精度更高,下面我们来证明一下:

这里我创建了一个表,里面两个属性的类型分别是float和decimal,m和d都相同,并且插入同样的数据。
但是我们从结果可以看到float类型和我们插入的数据并不完全相同,有精度的损失,但是decimal类型是完全相同的。
所以这个结果也证实了我们上面所说的结论,那么问题就来了:float精度不够,那它准确的精度是多少?decimal的精度又是多少呢?
1.对于float类型而言,float表示的精度大约是7位,超过7位,就会出现精度损失的情况
2.decimal整数的最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0。如果m被省略,默认是10。
除了上面的区别外,float和decimal就基本没什么区别了,所以就不过多赘述了。
三.字符串类型
3.1char类型
那么下面我们就来学习字符串类型,首先我们要讲的就是char类型:

char类型在这里就是我们所熟知的字符串,通过传入的L就可以指定存储的长度,这里注意:单位是字符,并不是字节,它们之间的区别通过下面的例子我们就会知道:

首先我们创建一个表,里面的name属性就是char类型,我们将其中的L设为2,表示字符串的最大的长度为2,单位为字符,那么下面我们想其中插入一些数据:


从上面的结果中我们可以看到当插入ab,cd这只占两个字节的字符串是没问题的,字符串超出范围MySQL也是会拦截我们的。
但是" 中国 "这个字符串占的可不是两个字节,对于编码格式utf8而言,每个汉字是占有3个字节的,所以" 中国 "这个字符串是占有6个字节的。
所以这里的单位字符可并不是我们常见的字节,不管是' a '还是' 中 ',在char类型中都看作是一个字符。

最后对于char类型而言,参数L的最大值为255,超出这个范围MuSQL是会对我们进行拦截的。
3.2varchar类型

而varchar类型和上面char类型很相似,用法上是一样的,同样表示的是字符串,参数L依旧表示的是字符长度,并且单位也是字符。
而在varchar类型中并没有限制L的大小,但是对于字符串所占有的总字节数做了限制,上面说最大长度不能超过65535个字节,那么65535个字节对应的L是多少呢?下面我们来试验一下:

当我们给参数L设置为65535时,MySQL拦截了我们,并说max也就是最大值为21845,那么下面我们重新进行传参试试:

但是但我们传入21845的时候发现依旧报错了,这是我们就会有一个很大的疑惑了:明明我传入的就是你规定范围内的数值,怎么还失败了呢?
答案就是在varchar类型中,是会有一个1~3字节的空间来记录数据的大小的,所以我们实际能够使用的空间就要比65535少1~3个字节,也就是我们传入的参数L也不能是21845,而要比21845要小。

可以看到我们传入21844就没有问题了。
但其实参数L所能设置的最大值是与表的编码密切相关的,什么意思呢?
意思就是当我们的表的编码是utf8时,varchar(L)的参数L最大值是65532(65535-3) / 3 = 21844(utf中,一个字符占3个字节)。
而如果编码是gbk,varchar(L)的参数L最大值是65532(65535-3) / 2 = 32766(gbk中,一个字符占2个字节)。
而因为我们默认的表的编码是utf8,所以上面我就以utf8为例来进行演示了,至于gbk的编码这里就不再演示了。
3.3char和varchar的比较
其实在上面展示char和varchar的概念时,我们其实也看到了它们的第一句话是固定长度字符串和可变长度字符串,那么这两个概念有什么区别呢?
固定长度字符串的意思就是我们给char类型的参数L传入255最大值,那么在底层就会真的为我们开辟255个字符的空间,不管这些空间你是否使用了,所以才称为固定长度字符串。
而可变长度字符串的意思就是我们给varchar类型的参数L传入了21844最大值,但是底层并不会真的就给我们开辟21844个字符的空间,而是你用多少给你开辟多少的空间,所以称为可变长度字符串。
那么我们在定义变量时如何选择定长还是变长字符串呢?
1.如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
2.如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。3.定长的磁盘空间比较浪费,但是效率高4.变长的磁盘空间比较节省,但是效率低
四.日期和时间类型
在MySQL中常用的日期类型有三个:
1.data:日期" yyyy-mm-dd ",占三个字节
2.datetime时间日期格式" yyyy-mm-dd HH:ii:ss "表示范围从1000到9999,占用8字节
3.timestamp:时间戳,从1970年开始的" yyyy-mm-dd HH:ii:ss "格式和datetime完全一致,占用四字节
那么下面我们就来演示一下这三种形式:

我们先创建一个表,里面的t1,t2和t3的类型分别就是date,datetime和timestamp,那么下面我们就向其中填入一些数据来看一看:

对于前面两个:date和datetime而言,我们就按照格式传入即可,但是最后的timestamp,它是时间戳,我们是不需要自己传入数据的,只需要调用NOW()函数获取当前时间即可。

可以看到当我们再次插入数据后,调用NOW()函数,timestamp时间戳就自己更新了,不需要我们手动更新。
五.enum和set
enum和set就是我们在C++语法中了解过的枚举和集合,那么对于它们具体的用法我们来看:

枚举和集合我们在C++中了解过,所以这里就不过多介绍了,下面我们直接来看示例:

这里我们就创建了一张表,gender属性的类型就是enum,里面的数据就是:男和女,hobby属性的类型是set,里面的数据是:登山,游泳,篮球和武术。
而对于它们两个我们一个一个来演示效果:

那么首先我们先来填充gender属性,而在上面的实验中,我们可以看到对于enum类型而言,我们传入' 男 ',' 女 '或者1,2都是可以的,而我们传入的不在这些数字中的数据时MySQL就会拦截我们。
enum要演示的就这么多了,下面我们重点来看set:



从上图的实验中我们可以看到对于set类型而言,我们插入数据时set中的数据可以单选也可以进行多选。
而上面set的介绍中也说了,set也是可以传数字的,下面我们就来传一传看看:
从上图的结果中我们可以看到确实可以插入数字,但是我们可以观察插入的数据可以发现:我们输入的数字按顺序是1,2,3,4,按理说插入的数据应该是登山,游泳,篮球和武术,但结果并不是我们所想的那样,这是为什么呢?
答案就是set中的数字并不代表下标,而是代表比特位,什么意思呢?下面我们来看:

我们插入了四个数值就相当于有四个比特位,这四个数据的下标值的其实是比特位的位置,所以说当我们输入1,2,3,4的时候,对应的比特位就如上图所示,所以才会是上面的结果。
相反的,当我们插入数据时输入数字,插入的数据也和上面的逻辑是一样的。
5.1查询set中的数据

当我们想要查询爱好中包含登山的数据时我们在输入指令的时候只能写:hobby=' 登山 ',但是这就局限了我们的搜索,从上图我们也可以看到我们查找的结果就是hobby只有登山的结果。
那么我们要该怎么做呢?
答案就是我们可以借助find_in_set函数,第一个参数就填写我们要查找的内容,后面跟的就是类型为set的属性。
最后我们通过结果可以看到此时就把整个表中hobby属性中含有登山的全部给查找了出来,解决了上面我们的问题。
以上就是一文通关 MySQL 数据类型,打好高性能数据库的第一战!的全部内容。