文章目录
- 数值类型
- 1、整数类型
- 2、浮点数类型
- 3、定点数类型
- 日期和时间类型
- 1、YEAR
- 2、DATE、TIME、DATETIME
- 3、TIMESTAMP
- 字符串类型
- 1、CHAR(M)
- 2、VARCHAR(M)
- 3、各种 TEXT 类型
- 4、ENUM 类型和 SET 类型
- 二进制类型
- 1、BIT 类型
- 2、BINARY(M) 与 VARBINARY(M)
- 3、BLOB 类型
MySQL说到底就是一个关系型数据库,底层存储数据不论是怎样,但是我们可以将数据库中的每一个表都看成是一张表格。一行就一个样本,每一列都是这个样本的某一个属性。所以每一列都有其数据类型。
数值类型
1、整数类型
| 类型【(有符号)/无符号】 | 占用空间 | 无符号取值范围 | 有符号取值范围 | 表示 |
|---|---|---|---|---|
| TINYINT (SIGNED)/UNSIGNED | 1字节 | 0 ∼ 2 8 − 1 ( 0 ∼ 255 ) 0 \sim 2^8 - 1(0 \sim 255) 0∼28−1(0∼255) | − 2 7 ∼ 2 7 − 1 ( − 128 ∼ 127 ) -2^7 \sim 2^7 - 1(-128 \sim 127) −27∼27−1(−128∼127) | 非常小的整数 |
| SMALLINT (SIGNED)/UNSIGNED | 2字节 | 0 ∼ 2 16 − 1 ( 0 ∼ 65535 ) 0 \sim 2^{16} - 1(0 \sim 65535) 0∼216−1(0∼65535) | − 2 15 ∼ 2 15 − 1 ( − 32768 ∼ 32767 ) -2^{15} \sim 2^{15} - 1(-32768 \sim 32767) −215∼215−1(−32768∼32767) | 小的整数 |
| MEDIUMINT (SIGNED)/UNSIGNED | 3字节 | 0 ∼ 2 24 − 1 ( 0 ∼ 1677215 ) 0 \sim 2^{24} - 1(0 \sim 1677215) 0∼224−1(0∼1677215) | − 2 23 ∼ 2 23 − 1 ( − 8388608 ∼ 8388607 ) -2^{23} \sim 2^{23} - 1(-8388608 \sim 8388607) −223∼223−1(−8388608∼8388607) | 中等大小的整数 |
| INT(INTEGER) (SIGNED)/UNSIGNED | 4字节 | 0 ∼ 2 32 − 1 ( 0 ∼ 4294967295 ) 0 \sim 2^{32} - 1(0 \sim 4294967295) 0∼232−1(0∼4294967295) | − 2 31 ∼ 2 31 − 1 ( − 2147483648 ∼ 2147483647 ) -2^{31} \sim 2^{31} - 1(-2147483648 \sim 2147483647) −231∼231−1(−2147483648∼2147483647) | 标准的整数 |
| BIGINT (SIGNED)/UNSIGNED | 8字节 | 0 ∼ 2 64 − 1 ( 0 ∼ 18446744073709551615 ) 0 \sim 2^{64} - 1(0 \sim 18446744073709551615) 0∼264−1(0∼18446744073709551615) | − 2 63 ∼ 2 63 − 1 ( − 9223372036854775808 ∼ 9223372036854775807 ) -2^{63} \sim 2^{63} - 1(-9223372036854775808 \sim 9223372036854775807) −263∼263−1(−9223372036854775808∼9223372036854775807) | 大整数 |
无符号类型必须添加 UNSIGNED,而有符号加不加 SIGNED 都可以。此外,现在不推荐使用 INT 而鼓励使用 INTEGER,其实两者是一样的。
2、浮点数类型
| 类型 | 占用空间 | 绝对值最小非零值 | 绝对值最大值 | 表示 |
|---|---|---|---|---|
| FLOAT | 4字节 | ± 1.175494351 E − 38 \pm 1.175494351E-38 ±1.175494351E−38 | ± 3.402823466 E + 38 \pm 3.402823466E+38 ±3.402823466E+38 | 单精度浮点数 |
| DOUBLE | 8字节 | ± 2.2250738585072014 E − 308 \pm 2.2250738585072014E-308 ±2.2250738585072014E−308 | ± 1.7976931348623157 E + 308 \pm 1.7976931348623157E+308 ±1.7976931348623157E+308 | 双精度浮点数 |
由于本身设计的原因,浮点数不仅无法表示某些小数,而且对一些小数的表示是不精确的。所以想保证所存储的小数是精确的,需要其他类型的数据类型,例如等下要介绍的定点数类型。
浮点数类型除了直接使用之外,还可以通过指定参数来限制表示的范围:
FLOAT(M, D)
DOUBLE(M, D)
其中 M 表示有效数字的个数,D 表示小数点后面需要保留的数字个数。例如 FLOAT(4, 1) 的取值范围为 -999.9 ~ 999.9。
当然,从MySQL8.0.17开始,MySQL已经不再推荐使用指定参数的方式了。
3、定点数类型
由于浮点数类型不能保证存储数据的精确度,所以MySQL又提出了定点数类型,它也是存储小数的一种方式:
| 类型 | 占用空间 | 取值范围 |
|---|---|---|
| DECIMAL(M, D) | 取决于 M 和 D | 取决于 M 和 D |
这里的 M 和 D 的含义与浮点数的相同,不过浮点数占用的存储空间不会随 M 和 D 的变化而变化,而定点数会。
另外,为了解决浮点数因为舍入操作而不精确的问题,定点数将十进制小数用小数点分开,将整数部分和小数部分分别存储起来。而为了尽量少的使用空间,定点数会从小数点开始,分别从左和从右,以9个位数为一组(不足9个位数也分为一组),把整个小数分成多个组,每个组以位数分配空间。
| 每个组的十进制位数 | 占用空间大小 |
|---|---|
| 1 或 2 | 1字节 |
| 3 或 4 | 2字节 |
| 5 或 6 | 3字节 |
| 7 或 8 或 9 | 4字节 |
例如现在有数据类型 DECIMAL(16, 4),它会被分为3组:

第一组包含3个十进制位,所以占2个字节;
第二组包含9个十进制位,所以占4个字节;
第三组包含4个十进制位,所以占2个字节;
综合所有情况,DECIMAL(16, 4) 会占用8个字节的空间大小。可以看出,当 M 和 D 确定的时候,这个数据类型所占用的空间也就确定了。
注意:这里指的 M 和 D 并不是实际存储数据的位数大小,而是最大值。例如我们可以使用 DECIMAL(16, 4) 存储拥有12个有效位数的数据 1234567890.12,而不一定必须存储16个有效位数,其中小数位数拥有4个的数据。
注意:当存储实际数据的时候,按照规则,我们还需要将转换完成的二进制位的最高位设置为1【这一步主要考虑到别的用途,暂且知道即可】。
以 DECIMAL(16, 4) 为定点数类型,其占用的空间是8个字节,让我们存储数据 1234567890.12。
- 从小数点往左数9个位数,即
234567890占用4个字节,为了方便,这里以十六进制表示为0x0DFB38D2; - 另外的
1占用2个字节,用十六进制表示为0x0001; - 小数点右边的
12占用2个字节,用十六进制表示为0x000C; - 于是得到了一个存储好的数
0x0001 0DFB38D2 000C(空格人为添加,请忽略); - 最后别忘记,还需要将第1个二进制位数的数置为1,于是最终结果为
0x8001 0DFB38D2 000C【注意是二进制的第一个数,转换为十六进制是8】;
如果我们需要存储负数,只需要将对应正数的二进制中的所有数值反转即可。例如 -1234567890.12,只需要将结果 0x8001 0DFB38D2 000C 的每个二进制位数值反转即可,为 0x7FFE F204C72D FFF3。
另外,M 的最大值65,D 的最大值为30,且 D 的值不能超过 M 的值。从MySQL8.0.17开始,MySQL也不建议在浮点数和定点数后面添加 UNSIGNED 来将它们设置为无符号类型。
虽然定点数类型的精度贼高,但是占用的空间也是不小,所以当不要求存储高精度的小数时,使用浮点数类型即可。
日期和时间类型
MySQL在5.6.4版本之前,TIME、DATETIME、TIMESTAMP 仅支持到秒,但是在这个版本之后,MySQL添加了对微秒的支持。
1
秒
=
1000
毫秒
=
1000000
微秒
1秒 = 1000毫秒 = 1000000微秒
1秒=1000毫秒=1000000微秒。
| 类型 | 占用空间 | 取值范围 | 表示 |
|---|---|---|---|
| YEAR | 1字节 | 1901 ∼ 2155 1901 \sim 2155 1901∼2155 | 年份值 |
| DATE | 3字节 | ′ 1000 − 01 − 0 1 ′ ∼ ′ 9999 − 12 − 3 1 ′ '1000-01-01' \sim '9999-12-31' ′1000−01−01′∼′9999−12−31′ | 日期值 |
| TIME | 3字节+小数秒的存储空间 | ′ − 838 : 59 : 59 [ . 000000 ] ′ ∼ ′ 838 : 59 : 59 [ . 000000 ] ′ '-838:59:59[.000000]' \sim '838:59:59[.000000]' ′−838:59:59[.000000]′∼′838:59:59[.000000]′ | 时间值 |
| DATETIME | 5字节+小数秒的存储空间 | ′ 1000 − 01 − 01 00 : 00 : 00 [ . 000000 ] ′ ∼ ′ 9999 − 12 − 31 23 : 59 : 59 [ . 999999 ] ′ '1000-01-01\ 00:00:00[.000000]' \sim '9999-12-31\ 23:59:59[.999999]' ′1000−01−01 00:00:00[.000000]′∼′9999−12−31 23:59:59[.999999]′ | 日期加时间值 |
| TIMESTAMP | 4字节+小数秒的存储空间 | ′ 1970 − 01 − 01 00 : 00 : 01 [ . 000000 ] ′ ∼ ′ 2038 − 01 − 19 03 : 14 : 07 [ . 999999 ] ′ '1970-01-01\ 00:00:01[.000000]' \sim '2038-01-19\ 03:14:07[.999999]' ′1970−01−01 00:00:01[.000000]′∼′2038−01−19 03:14:07[.999999]′ | 时间戳 |
可以看到,对于微秒的支持,其占用的空间也是变化的,它会随着小数秒的位数变化而占据不同的空间大小:
| 保留的小数秒的位数 | 额外占用的空间 |
|---|---|
| 0 | 0字节 |
| 1 或 2 | 1字节 |
| 3 或 4 | 2字节 |
| 5 或 6 | 3字节 |
例如 DATETIME(3) 表示支持3位小数秒,额外要占用2个字节,于是它占用的空间就是 5字节 + 2字节 = 7字节。
1、YEAR
它就是简单的年份值,如果想存储范围之外的年份,可以使用 SMALLINT 或者字符串类型。
2、DATE、TIME、DATETIME
接下来为了方便说明,使用 YYYY、MM、DD、hh、mm、ss、uuuuuu 分别表示年份值、月份值、天数、时、分、秒、小数秒。
DATE 表示日期,格式为 YYYY-MM-DD;
TIME 表示时间,格式为 hh:mm:ss[.uuuuuu]。它可以表示一天中的某个时间,也可以表示两个时间点之间的时间间隔,所以 TIME 表示的小时数可能非常大,并且可能为负值;
DATETIME 表示日期时间,格式为 YYYY-MM-DD hh:mm:ss[.uuuuuu]。其存储的时间必须是一天中的某一个时间点。
3、TIMESTAMP
全世界分为24个时区,我们中国则是以北京所在的东八区进行计时。而从0号时区的 1970-01-01 00:00:00 开始(也就是东八区的 1970-01-01 08:00:00)到现在所经历的秒数就被称为时间戳。
使用时间戳存储时间之后,可以让数据随着时区的变化而变化。而其他方式存储的时间数据都是固定的。
字符串类型
字符分为可见字符【例如敲键盘后能看见】和不可见字符【例如回车、空格】,多个字符连接起来就形成了字符串。
因为计算机只能存储二进制数,为了存储字符串,就需要一种方式,将字符映射为二进制数,这种映射过程就被称为字符编码。可以采用定长编码【固定转换后占用的空间】和变长编码【根据不同情况让字符占用不同的空间】。
| 类型 | 最大长度 | 占用空间 | 表示 |
|---|---|---|---|
| CHAR(M) | M个字符 | M × W M \times W M×W 字节 | 固定长度的字符串 |
| VARCHAR(M) | M个字符 | L + 1 L+1 L+1 或 L + 2 L+2 L+2 字节 | 可变长度的字符串 |
| TINYTEXT | $2^8-1 $ 个字节 | L + 1 L+1 L+1 字节 | 非常小的字符串 |
| TEXT | 2 16 − 1 2^{16}-1 216−1 个字节 | L + 2 L+2 L+2 字节 | 小的字符串 |
| MEDIUMTEXT | 2 24 − 1 2^{24}-1 224−1 个字节 | L + 3 L+3 L+3 字节 | 中等大小的字符串 |
| LONGTEXT | 2 32 − 1 2^{32}-1 232−1 个字节 | L + 4 L+4 L+4 字节 | 大的字符串 |
其中,M 代表该数据类型最多能存储的字符数量,L 代表实际存储的字符串在特定字符集中占用的字节数,W 代表在特定字符集中编码一个字符最多需要的字节数。
1、CHAR(M)
CHAR(M)类型中的 M 取值范围为
0
∼
255
0 \sim 255
0∼255,如果省略掉 M,那它的默认值就是1,也就是 CHAR 与 CHAR(1)是一个意思。比较特别的一种 CHAR 类型是 CHAR(0),它只能存储空字符串 '' 或者 NULL 值。
接下来看一下如何计算存储空间大小:
-
一个 CHAR(5) 类型采用 ASCII 码字符集。因为 ASCII 码字符集中一个字符最多占1个字节,所以 M = 5 M = 5 M=5, W = 1 W = 1 W=1,最终占用的字节数为 5 × 1 = 5 5 \times 1 = 5 5×1=5 字节。
-
如果实际存储的字符串小于5字节,剩余的那些空间会用空格字符(也就是
' ')补齐。
以此可知,如果 M 非常大,而我们向列中存储的字符串非常短时,就会浪费大量的空间。
2、VARCHAR(M)
VARCHAR(M) 跟 CHAR(M) 很像,不过 VARCHAR 的 M 范围更广,为
1
∼
65535
1 \sim 65535
1∼65535 字符数,而且 VARCHAR 占用的字节数是以实际存储的字符串大小为基础,为可变长度。
于是,VARCHAR(M) 在存储时共有两个部分。一个部分为实际存储的字符串占用的字节数,另一个部分则用来存储字节数这个数值。
下面看一下如何计算其存储空间大小:
- 真正的字符串内容:实际存储的字符串在特定字符集条件下占用的空间
L; - 占用的字节数:
- 假如 VARCHAR(M) 采用的字符集编码一个字符需要
W字节,于是有: - 当
M
×
W
<
256
M \times W < 256
M×W<256 时,只需要一个字节来表示占用的字节数【
2
8
−
1
=
255
2^{8} - 1 = 255
28−1=255】。最终得到存储空间为
L+1字节; - 当
M
×
W
≥
256
M \times W \ge 256
M×W≥256 时,需要两个字节来表示占用的字节数【
2
16
−
1
=
65535
2^{16} - 1 = 65535
216−1=65535】。最终得到存储空间为
L+2字节;
- 假如 VARCHAR(M) 采用的字符集编码一个字符需要
例如,如果采用 utf8mb3 字符集存储字符串“狗蛋”,数据类型为 VARCHAR(5)。其中,实际存储的“狗蛋”占用
3
×
2
=
6
3 \times 2 = 6
3×2=6 字节;又因为
M
×
W
=
3
×
5
=
15
M \times W = 3 \times 5 = 15
M×W=3×5=15,
15
<
256
15 < 256
15<256,所以存储6这个数值的空间仅占用一个字节。所以“狗蛋”总共占用7个字节。

3、各种 TEXT 类型
4种 TEXT 类型可以存储可变长度的字符串类型,开始的表格已经详细介绍,其中使用的多余字节数也是用来存储字节长度这个数值。
MySQL有一个规定,表的一行数据(包含多个列)占用的存储空间总共不得超过 65535 字节,但是这个规定对这些 TEXT 类型是不起作用的。如果一个表中有属性需要存储特别长的文本,就可以考虑这几个类型。
4、ENUM 类型和 SET 类型
ENUM 类型也被称为枚举类型,格式为 ENUM('str1', 'str2', 'str3', ...)。对于使用 ENUM 类型的列,它的值只能在给定的字符串列表中选择一个,相当于一个单选按钮。
那如果我们想像多选题一样选择多个,应该怎么做呢?MySQL提供了 SET 类型,它的格式为 SET('str1', 'str2', 'str3', ...)。使用 SET 类型的列可以在给定的字符串列表中选择一个或者多个。
二进制类型
1、BIT 类型
| 类型 | 占用的空间 | 表示 |
|---|---|---|
| BIT(M) | 近似为 ( M + 7 ) / 8 (M+7)/8 (M+7)/8 | 存储 M 个二进制位的值 |
有时候我们需要存储一个或者多个二进制位,此时就需要用到 BIT 类型。其中,M 的取值范围为
1
∼
64
1 \sim 64
1∼64,而且 M 可以省略,它的默认值为1。
它的存储方式跟上面的类型有些不同:
- BIT(1) 类型仅仅需要存储1比特数据,但是MySQL会申请 ( 1 + 7 ) / 8 = 1 (1+7)/8 = 1 (1+7)/8=1 字节(8比特)的空间;
- BIT(9) 类型仅需要存储7比特数据,但是MySQL会申请 ( 9 + 7 ) / 8 = 2 (9+7)/8 = 2 (9+7)/8=2 字节(16比特)的空间;
2、BINARY(M) 与 VARBINARY(M)
BINARY(M) 与 VARBINARY(M) 对应于前面提到的 CHAR(M) 与 VARCHAR(M)。不同点在于前者用来存放字节,后者用来存放字符。所以 M 在前者表示为最大字节数,后者表示为最大字符数。
3、BLOB 类型
有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB,它们用来存储可变长度的二进制数据,如图像、音频等。
它们很像 TEXT 类型,不过 BLOB 类型用来存储字节,而 TEXT 类型用来存储字符。
一般情况下,较大的图像、音频等数据不会直接存储到数据库种,而是存储在文件系统中,然后将文件路径存储到数据库中。



![[Android开发基础4] 点击事件的响应与处理](https://img-blog.csdnimg.cn/998d335e0fea4563a9fa59df294f0432.png)









![[架构之路-97]:《软件架构设计:程序员向架构师转型必备》-7-需求分析与业务需求领域建模](https://img-blog.csdnimg.cn/img_convert/ff8c9292e0d91f7235a2ff15d886d3ec.png)





