MySQL 字符类型一览

类型说明N的含义是否有字符集最大长度
CHAR(N)定长字符字符255
VARCHAR(N)变长字符字符16384
BINARY(N)定长二进制字节字节255
VARBINARY(N)变长二进制字节字节16384
TINYBLOB(N)二进制大对象字节256
BLOB(N)二进制大对象字节16K
MEDIUMBLOB(N)二进制大对象字节16M
LONGBLOB(N)二进制大对象字节4G
TINYTEXT(N)大对象字节256
TEXT(N)大对象字节16K
MEDIUMTEXT(N)大对象字节16M
LONGTEXT(N)大对象字节4G

不建议在MySQL中存储大型的二进制数据,比如歌曲,视频。

• 在BLOB和TEXT上创建索引时,必须指定索引前缀的长度,否则报错
mysql> create table test_text(a int primary key, b text, key(b(64)));
• BLOB和TEXT列不能有默认值
• BLOB和TEXT列排序时只使用该列的前max_sort_length个字节
mysql> select @@max_sort_length;

空格填充问题

create table cyt (name char(10)) charset=utf8;
select len(name) from cyt;

char(N)表示字符个数最多能容纳 N 个。

假设当前table的字符集的最大长度为 W Byte , 因为在 char(N) 中,N 表示 N 个字符,则 char(N) 的最大存储空间为 (N*W)Byte。
例如,假设使用 table 的字符集为 UTF-8 ,则char(10)可以最小存储10个字节的字符(10个字母),最大存储30个字节的字符(10个汉字)。

当存储的字符数小于N 时,尾部使用 空格 填充,并且填充最小字节的空格。

mysql> create table cyt (name char(10)) charset=utf8;
mysql> select name,length(name) from cyt;
+----------------+--------------+
| name           | length(name) |
+----------------+--------------+
| abc            |            3 |
| 我爱你         |            9 |
| 我爱你CN       |           11 |
| 我爱你呀CN     |           14 |
+----------------+--------------+

占用的字节长度很好理解,那么它们是如何填充空格的呢?
abc ---------- 填充 7 个空格(3个字符,不足10个,按最小字节数10计算,abc 占用3个字节,填充7个空格)
我爱你 ---------- 填充 1 个空格(3个字符,不足10个,按最小字节数10计算,我爱你 占用9个字节,填充1个空格)
我爱你CN ---------- 没有填充空格(5个字符,不足10个,按最小字节数10计算,我爱你CN 占用11个字节,不用填充空格)
我爱你呀CN ---------- 没有填充空格(6个字符,不足10个,按最小字节数10计算,我爱你呀CN 占用14个字节,不用填充空格)

我们看一下实际的存储情况:

mysql> select hex(' ');
+----------+
| hex(' ') |
+----------+
| 20       |
+----------+


mysql> select name, hex(name) from cyt;
+----------------+------------------------------+
| name           | hex(name)                    |
+----------------+------------------------------+
| abc            | 616263                       |
| 我爱你         | E68891E788B1E4BDA0           |
| 我爱你CN       | E68891E788B1E4BDA0434E       |
| 我爱你呀CN     | E68891E788B1E4BDA0E59180434E |
+----------------+------------------------------+


0000c070  73 75 70 72 65 6d 75 6d  0a 00 00 00 10 00 24 00  |supremum......$.|
0000c080  00 00 00 02 05 00 00 00  00 15 6d cd 00 00 01 58  |..........m....X|
0000c090  01 10 61 62 63 20 20 20  20 20 20 20 0a 00 00 00  |..abc       ....|
0000c0a0  18 00 24 00 00 00 00 02  06 00 00 00 00 15 6e ce  |..$...........n.|
0000c0b0  00 00 01 59 01 10 e6 88  91 e7 88 b1 e4 bd a0 20  |...Y........... |
0000c0c0  0b 00 00 00 20 00 4c 00  00 00 00 02 07 00 00 00  |.... .L.........|
0000c0d0  00 15 73 d1 00 00 01 5c  01 10 e6 88 91 e7 88 b1  |..s....\........|
0000c0e0  e4 bd a0 43 4e 0d 00 20  00 28 00 00 00 00 00 00  |...CN.. .(......|
0000c0f0  02 08 00 00 00 00 15 79  55 00 00 01 60 01 10 e6  |.......yU...`...|
0000c100  88 91 e7 88 b1 e4 bd a0  e5 91 80 43 0e 00 00 00  |...........C....|
0000c110  30 ff 5d 00 00 00 00 02  09 00 00 00 00 15 7b d6  |0.]...........{.|
0000c120  00 00 01 61 01 10 e6 88  91 e7 88 b1 e4 bd a0 e5  |...a............|
0000c130  91 80 43 4e 00 00 00 00  00 00 00 00 00 00 00 00  |..CN............|
0000c140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

注意:char 数据类型本来是定长数据,但是在多字节字符集下,表现的行为和varchar类似,失去了原来的优势,当数据更新变长后可能无法原地更新(关于原地更新可以参阅其它文章)。

如果将字段类型修改为 varchar(10),同样是插入上面的这些值,则都不会填充空格。

字符串比较问题

对于 char,插入值时,'a' 等于 'a ',用 length 计算长度时,都是1,但不等于 ' a';对于 varchar,尽管'a' 也等于 'a ',但用length 计算其长度时,前者为1,后都为4。
判断 'a' 与 'a ' 是否相待,是用校验规则来计算的。

上面的现象无法用统一的规则进行表述,但是官方文档给出的解释是,这样的安排是为了避免索引页的碎片。

-- By 许望(RHCA、OCM、VCP)
最后修改:2019 年 11 月 09 日 02 : 39 PM
如果觉得我的文章对你有用,请随意赞赏