暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL之数据类型

GrowthDBA 2021-09-13
1483



今天的文章主要介绍MySQL的数据类型。数据类型在面试中被问到的几率还是很大的,比如,各种整型的取值范围是多少、执行计划中key_len的值是如何计算的、前缀索引等等,这些面试题其实都和数据类型有关系,今天就来一起揭开数据类型的面纱。
本文摘录自小孩子4919《MySQL是怎样使用的:从零蛋开始学习MySQL》。


整数类型




进制和字节

在学习整数类型之前,还需要准备一些额外知识。
进制也就是进位计数制,是人为定义的带进位的计数方法。对于任何一种进制——X进制,就表示每一位置上的数运算时都是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。我们生活中最常用的就是十进制,从0~9,再加1就是10了,没法用像“9”这样一位数字来表示,必须得进一位,也就是“10”。而我们所说的计算机就是以二进制进行数据存储的(也就是常说的010101)。
二进制位(一个数字1或0所占用的位置)也可以被称为比特/比特位(英文名:bit,原义是binary digit),又因为计算机中8个比特位代表一个字节(字节是计算机用于计量存储容量的一种计量单位,英文名:Byte,简写:B,8bit=1B=1Byte),平时都是用若干个字节来表示一个整数,假如用1个字节表示109的话,那效果就是这样:01101101(二进制),假如用两个字节表示十进制数109的话,那效果就是这样:0000000001101101(二进制)。

MySQL整数类型

很显然,使用的字节数越多,意味着能表示的数值范围就越大,但是也就越耗费存储空间。根据表示一个数占用字节数的不同,MySQL把整数划分成如下所示的类型:

以TINYINT为例,用1个字节,也就是8个位表示有符号数的话,就是既可以表示正数,也可以表示负数的话,需要有一个比特位表示正负号。但是如果表示无符号数的话,也就是只表示非负数的话,就不需要表示正负号,这是有符号数无符号数的区别。(无符号数需要配合字段属性设置,相关内容请移步MySQL之字段属性ZEROFILL属性模块)

综上所述,有符号和无符号的取值范围差距还是很大的,因为二进制的缘故,相差范围达两倍。之前生产环境就遇到没有设置unsigned属性的主键字段快跑满的情况,如果跑满,数据将不会再被插入,所以当时将主键字段加上了unsigned属性,最大值从21亿提升到了42亿,这个跨度还是足够业务跑很长时间的。其实,业务中使用负数的情况很少,但也有,为了数据库的设计严谨性,MySQL把选择权交给了用户。
为什么最大值的计算要减1?其实最开始我了学习的时候,也很纳闷,为什么减1。后来也找了一些资料,加之自己的理解,得出以下的结论:其实减1只是为了便于计算,拿unsigned属性的1字节8比特位的TINYINT来说,最大值的二进制就是11111111,转换成十进制就是:255。但是范围是从0开始(0不是负数也不是正数),所以是0~255总共256(2⁸)个数,所以最大值就用公式:2⁸-1 来表示最大值。同时,如果最大值不减1,那就是2⁸=256,用二进制表示就是100000000,总共需要9个比特位,那就已经超出1字节了。(纯属加深印象的个人理解,如果从专业角度分析有误还请各位大佬勘误)除了TINYINT外,其余的整数类型都是按照这样的计算方式来计算最大值:2^[类型字节数×8]-1,如:unsigned的INT最大值就是:2³²-1。← 这样就很好理解了,我们也不用刻意去记住具体值了
为什么最小值不减1?首先说原因是正0和负0导致的,同样拿1字节8比特位的TINYINT来说,因为负号占用最高位一个比特位:(最前面的红色0表示正号,1表示负号)
正数部分:00000000~01111111
负数部分:10000000~11111111
这里有一个0值的差别:
00000000(正零)
10000000(负零)
从数学角度上,是没区别的。但是在计算机中,表示负值是用补码。虽然“-0”也是“0”,但根据正、反、补码体系,“-0”的补码和“+0”是不同的,这样就出现两个补码代表一个数值的情况。为了将补码与数字一一对应,所以认为规定“0”一律用“+0”表示。同时为了充分利用资源,就将原来本应该表示“-0”的补码规定为代表-128。所以符号位为1(含负值)时,让它去表示另外一个数好了。(重点:因为让它表示另外一个数,符号位就不是纯粹的符号位了,就代表符号位也会参与取反
原码:10000000
反码:01111111
补码:10000000(这时补码中的1代表的就是值了,而不是符号位了,计算其值就是128),于是10000000就表示-128(-2⁷),其实就是符号位被用来做了个补充,用来代表多出来的那个负数。
  • 原码、反码、补码详解移步:

https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html



浮点数类型




二进制表示十进制小数

浮点数是用来表示小数的,我们平时用的十进制小数也可以被转换成二进制后被计算机存储。比如9.875,这个小数可以被表示成这样:

9.875 = 8 + 0 + 0 + 1 + 0.5 + 0.25 + 0.125 = 1 × 2³ + 0 × 2² + 0 × 2¹ + 1 × 2⁰ + 1 × 2⁻¹ + 1 × 2⁻² + 1 × 2⁻³

也就是说,如果十进制小数9.875转换成二进制小数的话就是:1001.111。为了在计算机里存储这种二进制小数,我们统一把它们表示成a × 2ⁿ的科学计数法的形式,其中1≤|a|<2,比如1001.111可以被表示成1.001111 × 2³,我们把小数点之后的001111称为尾数,把中的3称为指数,然后只需要在计算机中的比特位中表示出尾数指数就行了。另外,小数也有正负之分,我们还需要单独的部分来表示小数的正负号。综上所述,表示一个浮点数需要下边几个部分:
  • 符号部分,占用1个比特位即可。

  • 指数部分,视具体浮点数格式而定。

  • 尾数部分,视具体浮点数格式而定。

MySQL的浮点数类型

很显然,我们表示一个浮点数使用的字节数越多,表示尾数和指数的范围就越大,也就是说可以表示的小数范围就越大,MySQL根据表示一个小数需要的不同字节数定义了如下的两种浮点数类型:

以单精度浮点数类型FLOAT类型为例,它占用的4个字节的各个组成部分如下图所示:

另外需要注意的是,虽然有的十进制小数,比如1.875可以被很容易的转换成二进制数1.111,但是更多的小数是无法直接转换成二进制的,比如说0.3,它转换成的二进制小数就是一个无限小数,但是我们现在只能用4个字节或者8个字节来表示这个小数,所以只能进行一些舍入来近似的表示,所以我们说计算机的浮点数表示有时是不精确的

设置最大位数和小数位数

在定义浮点数类型时,还可以在FLOAT或者DOUBLE后边跟上两个参数,就像这样:

FLOAT(M, D)
DOUBLE(M, D)

对于我们用户而言,使用的都是十进制小数。如果我们事先知道表中的某个列要存储的小数在一定范围内,我们可以使用FLOAT(M, D)或者DOUBLE(M, D)来限制可以存储到本列中的小数范围。其中:

  • M
    表示该小数最多需要的十进制有效数字个数

注意是有效数字
个数,比方说对于小数-2.3
来说有效数字个数就是2,对于小数0.9
来说有效数字个数就是1
  • D
    表示该小数的小数点后的十进制数字个数

这个好理解,小数点后有几个十进制数字,D
的值就是什么。
举个例子看一下,设置了M和D的单精度浮点数的取值范围的变化:

可以看到,在D相同的情况下,M越大,该类型的取值范围越大;在M相同的情况下,D越大,该类型的取值范围越小。当然,M和D的取值也不是无限大的,M的取值范围是1~255D的取值范围是0~30而且D的值必须不大于MM和D都是可选的,如果我们省略了它们,那它们的值按照机器支持的最大值来存储



定点数类型




正因为用浮点数表示小数可能会有不精确的情况,在一些情况下我们必须保证小数是精确的,所以MySQL提出一种称之为定点数的数据类型,它也是存储小数的一种方式:

此处的M和D的含义与浮点数中的含义一样。M和D对取值范围的影响我们之前在唠叨浮点数的时候已经介绍过了,但是我们又说单精度浮点数类型FLOAT(M, D)占用的字节数一直都是4字节,双精度浮点数DOUBLE(M, D)占用的字节数一直都是8字节,它们占用的存储空间大小并不随着M和D的值的变动而变动。这个所谓的定点数类型DECIMAL(M, D),它占用的存储空间大小取决于M、D的取值。

我们说定点数是一种精确的小数,为了达到精确的目的我们就不能把它转换成二进制小数之后再存储(因为有很多十进制小数转为二进制小数后需要进行舍入操作,导致二进制小数表示的数值是不精确的)。其实转念一想,所谓的小数只是把两个十进制整数用小数点分割开来而已,我们只要把小数点左右的两个十进制整数给存储起来,那不就是精确的了么。比方说对于十进制小数2.38来说,我们可以把这个小数的小数点左右的两个整数,也就是2和38分别保存起来,那么不就相当于保存了一个精确的小数么,这波操作是不是很6。

当然事情并没有这么简单,对于给定M、D值的DECIMAL(M, D)类型,比如DEMCIMAL(16, 4)来说:

  • 首先确定小数点左边的整数最多需要存储的十进制位数是12位,小数点右边的整数需要存储的十进制位数是4位,如图所示:

从小数点位置出发,每个整数每隔9个十进制位划分为1组,效果就是这样:

图中可以看出,如果不足9个十进制位,也会被划分成一组。

针对每个组中的十进制数字,将其转换为二进制数字进行存储,根据组中包含的十进制数字位数不同,所需的存储空间大小也不同,具体见下表:

所以DECIMAL(16, 4)
共需要占用8
个字节的存储空间大小,这8个字节由下边3个部分组成:

  • 第1组包含3个十进制位,需要使用2个字节存储。

  • 第2组包含9个十进制位,需要使用4个字节存储。

  • 第3组包含4个十进制位,需要使用2个字节存储。

将转换完成的比特位序列的最高位设置为1。
举个栗子🌰说一下:
比方说我们使用定点数类型DECIMAL(16, 4)来存储十进制小数1234567890.1234,这个小数会被划分成3个部分:
1 234567890 1234
也就是:
  • 第1组中包含整数1。
  • 第2组中包含整数234567890。
  • 第3组中包含整数1234。
然后将每一组中的十进制数字转换成对应的二进制数字:
  • 第1组占用2个字节,整数1对应的二进制数就是(字节之间实际上没有空格,只不过为了大家理解上的方便我们加了一个空格):
00000000 00000001

二进制看起来太难受,我们还是转换成对应的十六进制看一下:

0x0001

  • 第2组占用4个字节,整数234567890对应的十六进制数就是:

0x0DFB38D2
  • 第3组占用2个字节,整数1234对应的十六进制数就是:
0x04D2
所以将这些十六进制数字连起来之后就是:
0x00010DFB38D204D2
最后还要将这个结果的最高位设置为1,所以最终十进制小数1234567890.1234使用定点数类型DECIMAL(16, 4)存储时共占用8个字节,具体内容为:
0x80010DFB38D204D2
如果我们想使用定点数类型DECIMAL(16, 4)存储一个负数怎么办,比方说-1234567890.1234,这时只需要将0x80010DFB38D204D2中的每一个比特位都执行一个取反操作就好,也就是得到下边这个结果:
0x7FFEF204C72DFB2D
从上边的叙述中我们可以知道,对于DECIMAL(M, D)类型来说,给定的M和D的值不同,所需的存储空间大小也不同。可以看到,与浮点数相比,定点数需要更多的空间来存储数据,所以如果不是在某些需要存储精确小数的场景下,一般的小数用浮点数表示就足够了。
对于定点数类型DECIMAL(M, D)来说,M和D都是可选的,默认的M的值是10,默认的D的值是0,也就是说下列等式是成立的:
DECIMAL = DECIMAL(10) = DECIMAL(10, 0)
DECIMAL(n) = DECIMAL(n, 0)
另外M的范围是1~65,D的范围是0~30,且D的值不能超过M



无符号数值类型的表示




对于数值类型,包括整数、浮点数和定点数,有些情况下我们只需要用到无符号数(就是非负数)。MySQL给我们提供了一个表示无符号数值类型的方式,就是在原数值类型后加一个单词UNSIGNED:
数值类型 UNSIGNED
大家可以把它当成一种新类型对待,比如INT UNSIGNED就表示无符号整数,FLOAT UNSIGNED表示无符号浮点数,DECIMAL UNSIGNED表示无符号定点数。
注意:在使用的存储空间大小相同的情况下,无符号整数可以表示的正整数范围比有符号整数能表示的正整数范围大一倍。不过受浮点数和定点数具体的存储格式影响,无符号浮点数和定点数并不能提升正数的表示范围。



日期和时间类型




我们有很多场景需要表示时间或日期,比如学生基本信息中的入学时间就需要用日期的格式保存。MySQL为我们提供了多种关于时间和日期的类型,各种类型能表示的范围如下:

在MySQL 5.6.4这个版本之后,TIME、DATETIME、TIMESTAMP这几种类型添加了对毫秒、微秒的支持。由于毫秒、微秒都不到1秒,所以也被称为小数秒,MySQL最多支持6位小数秒的精度,各个位代表的意思如下:

如果我们想让TIME、DATETIME、TIMESTAMP这几种类型支持小数秒,可以这样写:

  • 类型(小数秒位数)

  • 其中的小数秒位数可以在0、1、2、3、4、5、6中选择

比如DATETIME(0)表示精确到秒,DATETIME(3)表示精确到毫秒,DATETIME(5)表示精确到10微秒。如果你在选择TIME、DATETIME、TIMESTAMP这几种类型的时候添加了对小数秒的支持,那么所需的存储空间需要相应的扩大,保留不同的小数秒位数,那么增加的存储空间大小也不同,如下表:

也就是说如果你选择使用DATETIME(1),那么需要的存储空间就是在DATETIME的空间上再加上小数秒需要的空间,就是8 + 1 = 9个字节,类似的,DATETIME(3)就需要8 + 2 = 10个字节。所以,MySQL 5.6.4这个版本之后的各个类型需要的存储空间和取值范围就如下:

大家应该发现其中的在没有存储小数秒的情况下,DATETIME类型占用的存储空间从原来的8字节变成了5字节,这是因为MySQL背后做了些努力,使存储格式变得更紧凑了些。

当然,如果你使用的MySQL版本还没到5.6.4,那就不支持小数秒,可以翻上去看原来的存储空间和取值范围。下边我们来详细看一下各种类型。

YEAR

YEAR类型也可以写成YEAR(4),它单纯表示一个年份值,取值范围为1901 ~ 2155,仅仅占用1个字节大小而已。因为可以存储的年份值有限,如果我们想存储更大范围的年份值,可以不使用MySQL自带的YEAR类型换成SMALLINT(2字节)或者字符串类型啥的都可以

曾经也有YEAR(2)这种使用2个数字来表示年份的类型,比方说数字99表示1999年。不过在MySQL 5.7.5之后就不再支持这种类型了,因为可能会产生歧义,上篇文章MySQL之DQL语句(四)有提到过,我们稍微了解一下就好了。

DATE、TIME和DATETIME

顾名思义,DATE表示日期,格式是YYYY-MM-DDTIME表示时间,格式是hh:mm:ss[.uuuuuu]或者hhh:mm:ss[.uuuuuu](有时候要存储的小时值是三位数),DATETIME表示日期+时间,格式是YYYY-MM-DD hh:mm:ss[.uuuuuu]。其中的YYYYMMDDhhmmssuuuuuu分别表示年、月、日、时、分、秒、小数秒。

需要注意的是,DATETIME中的时间部分表示的是一天内的时间(00:00:00 ~ 23:59:59),而 TIME表示的是一段时间,而且可以表示负值。

TIMESTAMP

1970-01-01 00:00:00注定是一个特殊的时刻,我们把某个时刻距离1970-01-01 00:00:00的秒数称为时间戳。比方说当前时间是2018-01-24 11:39:21,距离1970-01-01 00:00:00的秒数为1516765161,那么2018-01-24 11:39:21这个时刻的时间戳就是1516765161。不过在MySQL 5.6.4之后,时间戳的值也可以加入小数秒。

用时间戳存储时间的好处就是,它展示的值可以随着时区的变化而变化。比方说我们把2018-01-24 11:39:21这个时刻存储到一个TIMESTAMP的列中,那么在中国你看到的时间就是2018-01-24 11:39:21,如果你去了日本,他们哪里的使用的是东京时间,比北京时间早一个小时,所以他们那显示的就是2018-01-24 12:39:21。而如果你用DATETIME存储2018-01-24 11:39:21的话,那不同时区看到的时间值都是一样的。




字符串类型




现在来看一下MySQL中提供的各种字符串类型(注:其中M代表该数据类型最多能存储的字符数量,L代表我们实际向该类型的属性中存储的字符串在特定字符集(字符集的相关知识移步之前的文章MySQL之字符编码)下所占的字节数,W代表在该特定字符集下,编码一个字符最多需要的字节数):

CHAR(M)

CHAR(M)中的M代表该类型最多可以存储的字符数量,注意,是字符数量,不是字节数量。其中M的取值范围是0~255。如果省略掉M的值,那它的默认值就是1,也就是说CHARCHAR(1)是一个意思。CHAR(0)是一种特别的类型,它只能存储空字符串''或者NULL值。再回头看一眼我们的学生基本信息表,如果你觉得学生的姓名不会超过5个字符,你就可以指定这个姓名列的类型为CHAR(5)。

CHAR(M)在不同的字符集下需要的存储空间也是不一样的,我们假设某个字符集编码一个字符最多需要W个字节,那么类型CHAR(M)占用的存储空间大小就是M×W个字节。比方说:

  • 对于采用ascii字符集的CHAR(5)类型来说,ascii字符集编码一个字符最多需要1个字节,也就是M=5、W=1,所以这种情况下该类型占用的存储空间大小就是5×1 = 5个字节。
  • 对于采用gbk字符集的CHAR(5)类型来说,gbk字符集编码一个字符最多需要2个字节,也就是M=5、W=2,所以这种情况下该类型占用的存储空间大小就是5×2 = 10个字节。
  • 对于采用utf8字符集的CHAR(5)类型来说,utf8字符集编码一个字符最多需要3个字节,也就是M=5、W=3,所以这种情况下该类型占用的存储空间大小就是5×3 = 15个字节。

如果我们实际存储的字符串在特定字符集编码下占用的字节数不足M×W,那么剩余的那些存储空间用空格字符(也就是:' ')补齐。比方说表的某个属性的类型是采用ascii字符集的CHAR(5)类型,我们想将字符串'abc'存入使用这个类型的表属性中,其中字符串'abc'在ascii字符集下需要3个字节存储,而采用ascii字符集的CHAR(5)类型又需要5个字节的存储空间,那么剩下的那两个字节的存储空间就会存储空格字符' '的编码。这也就是说:一旦你确定了CHAR(M)类型的M的值,如果M的值很大,而你实际存储的字符串占用字节数又很少,会造成存储空间的浪费。

补充一点,CHAR和VARCHAR虽然分别用于存储定长和变长字符,但对于变长字符集(如GBK、UTF8MB4),其本质是一样的,都是变长,设计时完全可以用VARCHAR替代CHAR,CHAR(1)既可以存储1个'a' 字节,也可以存储4个字节的emoji笑脸表情,因此CHAR本质也是变长的。看图。

VARCHAR(M)

如果你表中的某个列需要存储字符串类型的数据,而且这些字符串长短不一,那么使用CHAR(M)可能会浪费很多存储空间,VARCHAR(M)正是为了解决这个问题而生的。

VARCHAR(M)中的M也是代表该类型最多可以存储的字符数量,理论上的取值范围是1~65535。但是MySQL中还有一个规定,表中某一行包含的所有列中存储的数据大小总共不得超过65535个字节(注意是字节),也就是说VARCHAR(M)类型实际能够容纳的字符数量是小于65535的

VARCHAR(M)类型占用的存储空间不确定,那系统在读一个VARCHAR(M)类型的数据时怎么知道该数据占用多少个字节呢?答案是:不知道。所以一个VARCHAR(M)类型表示的数据其实是由这么两部分组成:

1、真正的字符串内容。
假设真正的字符串在特定字符集编码后占用的字节数为L
2、占用字节数。
假设VARCHAR(M)类型采用的字符集编码一个字符最多需要W个字节,那么:
  • M×W < 256时,只需要一个字节来表示占用的字节数。

  • M×W >= 256M×W < 65536时,需要两个字节来表示占用的字节数。

小贴士:一个字节占用8个比特位,能表示的最大无符号数就是255,两个字节占用16个比特位,能表示的最大无符号数就是65535。
VARCHAR(M)类型占用的存储空间大小随着实际存储的内容变化而变化,假设实际存储的内容占用的字节长度为L,那么整个VARCHAR(M)类型占用的存储空间大小就是L+1或者L+2个字节。所以我们说VARCHAR(M)是一种可变长度的字符串类型。

各种TEXT类型

虽然VARCHAR(M)已经可以存储很长的字符串了,可是有时候还是不够咋办?对于很长的字符串,设计MySQL的大叔们给我们提供了TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT四种可以存储大型的字符串的类型。它们也都是变长类型,也就是说这些类型占用的存储空间由实际内容和内容占用的字节长度两部分构成。

  • 因为TINYTEXT最多可以存储2⁸-1个字节,所以内容占用的字节长度用1个字节就可以表示
  • TEXT最多可以存储2¹⁶-1个字节,所以内容占用的字节长度用2个字节就可以表示。
  • MEDIUMTEXT最多可以存储2²⁴-1个字节,所以内容占用的字节长度用3个字节就可以表示。
  • LONGTEXT最多可以存储2³²-1个字节,所以内容占用的字节长度用4个字节就可以表示。

不过之前不是有个规定说某一行包含的所有列中存储的数据大小总和不得超过65535个字节么?这个规定对这些TEXT类型是不起作用的,它们并不在这个规定的限制范围之内。一个表中如果有的属性需要存储特别长的文本的话,就可以考虑使用这几个类型了。

今天看到一个很有意思的问题:“要是字段总是显示text(0)这个是显示错误还是有什么特殊含义?text可以限定字段长度吗?”,之前因为MySQL开发规范中禁止使用TEXT类型,所以也没有遇到过这样的问题,所以做了一个实验。

结论:TEXT(0)会变成TINYTEXT

ENUM类型和SET类型

视角回到我们的学生信息表,性别一列也需要填写字符串,但是比较特殊的一点是,这一列只能填男或者女,填别的字符串就尴尬了!针对这种情况,我们提出了一个叫ENUM的类型,也称为枚举类型,它的格式如下:

ENUM('str1', 'str2', 'str3' ⋯)

它表示在给定的字符串列表里选择一个。比如我们的性别一列可以定义成ENUM('男', '女')类型。这个的意思就是性别一列只能在'男'或者'女'两个字符串之间选择一个,相当于一个单选框

有的时候某一列的值可以在给定的字符串列表中挑选多个,假设学生的基本信息加了一列兴趣属性,这个属性的值可以从给定的兴趣列表中挑选多个,那我们可以使用SET类型,它的格式如下:
SET('str1', 'str2', 'str3' ⋯)

它表示可以在给定的字符串列表里选择多个。我们的兴趣一列就可以定义成SET('打球', '画画', '扯犊子', '玩游戏')类型。这个的意思就是兴趣一列可以在给定的这几个字符串中选择一个或多个,相当于一个多选框。

综上所述,ENUM和SET类型都是一种特殊的字符串类型,在从字符串列表中单选或多选元素的时候会用得到它们。




二进制类型




BIT类型

有时候我们有存储单个或者多个比特位的需求,此时就可以用到下边这种类型:

其中M的取值范围为1~64,而且M可以省略,它的默认值为1,也就是说BIT(1)和BIT的意思是一样的。
MySQL是以字节为单位存储数据的,一个字节拥有8个比特位。如果我们想存储的比特位个数不足整数个字节,那么MySQL会偷偷的填充满,比方说:
  • BIT(1)类型仅仅需要存储1个比特位的数据,但是MySQL会为其申请(1+7)/8 = 1个字节。

  • BIT(5)类型仅仅需要存储5个比特位的数据,但是MySQL会为其申请(5+7)/8 = 1个字节。

  • BIT(9)类型仅仅需要存储9个比特位的数据,但是MySQL会为其申请(9+7)/8 = 2个字节。

BINARY(M)与VARBINARY(M)

BINARY(M)VARBINARY(M)对应于我们前边提到的CHAR(M)和VARCHAR(M),都是前者是固定长度的类型,后者是可变长度的类型,只不过BINARY(M)和VARBINARY(M)是用来存放字节的,其中的M代表该类型最多能存放的字节数量,而CHAR(M)和VARCHAR(M)是用来存储字符的,其中的M代表该类型最多能存放的字符数量。

其他的二进制类型

TINYBLOBBLOBMEDIUMBLOBLONGBLOB是针对数据量很大的二进制数据提出的,比如图片、音频、压缩文件啥的。它们很像TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT,不过各种BLOB类型是用来存储字节的,而各种TEXT类型是用来存储字符的而已

小贴士:对于比较大的二进制数据,比方说图片、音频、压缩文件什么的,通常情况下都不直接存储到数据库管理系统中,而是将它们保存到文件系统中,然后在数据库中之存放一个文件路径即可。




小结





今天分享的内容是比撒哈拉沙漠还干的干货,内容比较多,但每一个知识点都是工作中会经常接触到、面试中出现频率较高的。小孩子4919大佬的语言非常通俗易懂,在整理摘录过程中,也包含了我的一些理解和一些经过测试得到的结论。所以,希望通过这篇文章,能让大家彻底掌握MySQL的数据类型。站在巨人肩膀上共同进步。



end


文章转载自GrowthDBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论