官方文档地址:11.3.3 The BINARY and VARBINARY Types
BINARY
和VARBINARY
类型与CHAR
和VARCHAR
类似,不同之处是它们存储的是二进制字符串而不是非二进制字符串。也就是说,它们存储的是字节字符串而不是字符字符串。这意味着它们具有二进制字符集和排序规则,比较和排序基于值中字节的数值。
BINARY
和VARBINARY
允许的最大长度与CHAR
和VARCHAR
相同,不同的是BINARY
和VARBINARY
的长度是以字节而不是字符来度量的。
BINARY
和VARBINARY
数据类型不同于CHAR BINARY
和VARCHAR BINARY
数据类型。对于后一种类型,BINARY
属性不会使列被视为二进制字符串列。相反,它会导致该列使用字符集的二进制(_bin
)排序规则(如果没有指定列字符集,则使用表默认字符集),并且列本身存储非二进制字符字符串而不是二进制字节字符串。例如,如果默认字符集为utf8mb4
,则CHAR(5) BINARY
将被视为CHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
。这与BINARY(5)
不同,BINARY(5)
存储具有二进制字符集和排序规则的5
字节二进制字符串。有关二进制字符集的二进制排序规则和非二进制字符集的_bin
排序规则之间的区别的信息,请参阅 10.8.5 二进制排序规则与 _bin 排序规则的比较。
如果没有启用严格 SQL 模式,并且将超过列最大长度的值分配给BINARY
或VARBINARY
列,该值会被截断以适合列的最大长度,并生成警告。要禁止非空格字符的截断,可以使用严格的 SQL 模式导致出现错误(而不是警告)并禁止插入值。参见 5.1.11 服务器 SQL 模式。
当存储BINARY
值时,它们将被右填充为指定长度的填充值。pad 值是0x00
(零字节)。值在插入时用0x00
右填充,检索时不删除尾随字节。所有的字节在比较中都是重要的,包括ORDER BY
和DISTINCT
操作。0x00
和空格在比较时是不同的,0x00
在空格之前排序。
例如:对于一个BINARY(3)
列,'a '
在插入时变成'a \0'
。'a\0'
在插入时变成'a\0\0'
。两个插入的值在检索时都保持不变。
对于VARBINARY
,插入时没有填充,检索时也没有字节剥离。所有的字节在比较中都是重要的,包括ORDER BY
和DISTINCT
操作。0x00
和空格在比较时是不同的,0x00
在空格之前排序。
对于那些删除了尾随字节或在比较时忽略它们的情况,如果列具有唯一值的索引,则向列中插入仅在尾随字节数量上不同的值将导致重复键错误。例如,如果一个表包含'a'
,尝试存储'a\0'
会导致重复键错误。
如果计划使用BINARY
数据类型存储二进制数据,并且要求检索到的值与存储的值完全相同,则应该仔细考虑前面的填充和剥离特征。下面的例子说明了BINARY
值的0x00
填充如何影响列值的比较:
mysql> CREATE TABLE t (c BINARY(3));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t SET c = 'a';
Query OK, 1 row affected (0.01 sec)
mysql> SELECT HEX(c), c = 'a', c = 'a\0\0' from t;
+--------+---------+-------------+
| HEX(c) | c = 'a' | c = 'a\0\0' |
+--------+---------+-------------+
| 610000 | 0 | 1 |
+--------+---------+-------------+
1 row in set (0.09 sec)
如果检索到的值必须与未填充的存储指定的值相同,则最好使用VARBINARY
或一种BLOB
数据类型。