mysql 常见数据类型
MySQL 是以字节为单位存储数据的,一个字节拥有8个比特位。如果存储的不足 1 个字节,MySQL 会自动填充成 1 个字节。
- 字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
- 字符集(Character set)是一个系统支持的所有抽象字符的集合。
- 字符编码(Character encoding)是把字符集中的字符编码为特定的二进制数,以便在计算机中存储。每个字符集中的字符都对应一个唯一的二进制编码。
1 字符编码
字符是面向人的概念,字节是面向计算机的概念。如果想在计算机中表示字符,那就需要将该字符与一个特定的字节序列对应起来,这个映射过程称之为编码。但是,这种映射关系并不是唯一的,不同的人制作了不同的编码方案。
根据表示一个字符使用的字节数量是不是固定的,编码方案可以分为以下两种:
1.1 定长编码
表示不同的字符所需要的字节数量是相同的。比如 ASCII 编码方案采用 1 个字节来编码一个字符,ucs2 采用 2 个字节来编码一个字符。
1.2 变长编码
表示不同的字符所需要的字节数量是不同的。比方说 utf8 编码方案采用 13 个字节来编码一个字符,gb2312 采用 12 个字节来编码一个字符。
对于不同的字符编码方案来说,同一个字符可能被编码成不同的字节序列。比如同样一个字符:我
,在 utf8 和 gb2312 这两种编码方案下被映射成如下的字节序列:
- utf8 编码方案
字符我
被编码成 111001101000100010010001
,共占用 3 个字节,用十六进制表示就是:0xE68891
。
- gb2312 编码方案
字符我
被编码成 1100111011010010
,共占用 2 个字节,用十六进制表示就是:0xCED2
。
MySQL 对编码方案和字符集这两个概念并没做什么区分,也就是说 utf8 字符集指的就是 utf8 编码方案,gb2312 字符集指的也就是 gb2312 编码方案。
正宗的 utf8 字符集是使用 1~4 个字节来编码一个字符的,不过MySQL中对utf8字符集做了阉割,编码一个字符最多使用3个字节。 如果有存储使用4个字节来编码的字符的情景,可以使用一种称之为utf8mb4的字符集,它才是正宗的utf8字符集。
2 整数
类型 | 占用空间 | 无符号数取值范围 | 有符号数取值范围 | 含义 |
---|---|---|---|---|
TINYINT | 1 | 0 ~ 2⁸-1 |
-2⁷ ~ 2⁷-1 |
非常小的整数 |
SMALLINT | 2 | 0 ~ 2¹⁶-1 |
-2¹⁵ ~ 2¹⁵-1 |
小的整数 |
MEDIUMINT | 3 | 0 ~ 2²⁴-1 |
-2²³ ~ 2²³-1 |
中等大小的整数 |
INT(别名:INTEGER) | 4 | 0 ~ 2³²-1 |
-2³¹ ~ 2³¹-1 |
标准的整数 |
BIGINT | 8 | 0 ~ 2⁶⁴-1 |
-2⁶³ ~ 2⁶³-1 |
大整数 |
3 浮点数
类型 | 占用空间 | 绝对值最小非0值 | 绝对值最大非0值 | 含义 |
---|---|---|---|---|
FLOAT | 4 | ±1.175494351E-38 |
±3.402823466E+38 |
单精度浮点数 |
DOUBLE | 8 | ±2.2250738585072014E-308 |
±1.7976931348623157E+308 |
双精度浮点数 |
有的十进制小数,比如 1.875 可以被很容易的转换成二进制数 1.111 ,但是更多的小数是无法直接转换成二进制的,比如说 0.3 ,它转换成的二进制小数就是一个无限小数,但是现在只能用 4 个字节或者 8 个字节来表示这个小数,所以只能进行一些舍入来近似的表示,所以说计算机的浮点数表示有时是不精确的。
3.1 设置最大最小位数
可以使用 FLOAT(M, D)
或者 DOUBLE(M, D)
来限制可以存储到本列中的小数范围。其中:
M
表示该小数最多需要的十进制有效数字个数。
D
表示该小数的小数点后的十进制数字个数。
M
的取值范围是1~255
,D
的取值范围是0~30
,而且D
的值必须不大于M
。
M
和D
都是可选的,如果省略,它们的值按照机器支持的最大值来存储。
计算十进制有效数字个数时,不计入正负号,不计入最左边的 0,也不计入小数点。所以
-2.3
来说有效数字个数就是 2,0.9
有效数字个数就是 1。
4 定点数
因为用浮点数表示小数可能会有不精确的情况,在一些情况下我们必须保证小数是精确的,可以使用定点数的数据类型。
与浮点数相比,定点数需要更多的空间来存储数据,所以如果不是在某些需要存储精确小数的场景下,一般的小数用浮点数表示就足够了。
类型 | 占用空间 | 取值范围 |
---|---|---|
DECIMAL(M, D) | 取决于M和D | 取决于M和D |
DECIMAL 如果不指定精度,默认的 M 的值是 10 ,默认的 D 的值是 0,也就是说下列等式是成立的:
DECIMAL = DECIMAL(10) = DECIMAL(10, 0)
DECIMAL(n) = DECIMAL(n, 0)
M 的范围是 1~65
,D的范围是0~30
,且D
的值不能超过M
。
5 无符号数值
对于数值类型,包括整数、浮点数和定点数,有些情况下只需要用到无符号数(就是非负数)。
MySQL 提供了一个表示无符号数值类型的方式,就是在原数值类型后加一个单词UNSIGNED
:
数值类型 UNSIGNED
可以把它当成一种新类型对待,比如INT UNSIGNED
就表示无符号整数,FLOAT UNSIGNED
表示无符号浮点数,DECIMAL UNSIGNED
表示无符号定点数。
在使用的存储空间大小相同的情况下,无符号整数可以表示的正整数范围比有符号整数能表示的正整数范围大一倍。 不过受浮点数和定点数具体的存储格式影响,无符号浮点数和定点数并不能提升正数的表示范围。
6 时间和日期
类型 | 存储空间 | 取值范围 | 含义 |
---|---|---|---|
YEAR | 1 | 1901 ~2155 |
年份值 |
DATE | 3 | 1000-01-01 ~9999-12-31 |
日期值 |
TIME | 3 | -838:59:59 ~838:59:59 |
时间值 |
DATETIME | 8 | 1000-01-01 00:00:00 ~9999-12-31 23:59:59 |
日期加时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:01 ~2038-01-19 03:14:07 |
时间戳 |
TIME
表示时间,格式是hh:mm:ss[.uuuuuu]
或者hhh:mm:ss[.uuuuuu]
用时间戳存储时间的好处就是,它展示的值可以随着时区的变化而变化。
DATETIME 中的时间部分表示的是一天内的时间(00:00:00 ~ 23:59:59),而 TIME 表示的是一段时间,而且可以表示负值。
7 字符串
类型 | 最大长度 | 存储空间要求 | 含义 |
---|---|---|---|
CHAR(M) | M个字符 | M×W个字节 | 固定长度的字符串 |
VARCHAR(M) | M个字符 | L+1 或 L+2 个字节 | 可变长度的字符串 |
TINYTEXT | 2⁸-1 个字节 | L+1个字节 | 非常小型的字符串 |
TEXT | 2¹⁶-1 个字节 | L+2 个字节 | 小型的字符串 |
MEDIUMTEXT | 2²⁴-1 个字节 | L+3个字节 | 中等大小的字符串 |
LONGTEXT | 2³²-1 个字节 | L+4个字节 | 大型的字符串 |
M
代表该数据类型最多能存储的字符数量,L
代表我们实际向该类型的属性中存储的字符串在特定字符集下所占的字节数,W
代表在该特定字符集下,编码一个字符最多需要的字节数。
VARCHAR(M)
中的M
也是代表该类型最多可以存储的字符数量,理论上的取值范围是 1~65535。但是MySQL中还有一个规定,表中某一行包含的所有列中存储的数据大小总共不得超过 65535
个字节,也就是说 VARCHAR(M)
类型实际能够容纳的字符数量是小于 65535 的。