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 ' 是否相待,是用校验规则来计算的。
上面的现象无法用统一的规则进行表述,但是官方文档给出的解释是,这样的安排是为了避免索引页的碎片。