13.3.3 二进制和可变二进制类型
BINARY
和 VARBINARY
类型类似于CHAR
和VARCHAR
,except 他们存储二进制字符串,而不是非二进制字符串。也就是说,他们存储字节串,而不是字符串。这意味着它们具有binary
字符集和排序规则,并且比较和排序基于值中的字节的数字值。
BINARY
和 VARBINARY
的最大允许长度与CHAR
和VARCHAR
相同,except BINARY
和 VARBINARY
的长度以字节为单位,而不是字符为单位。
BINARY
和 VARBINARY
数据类型与 CHAR BINARY
和 VARCHAR BINARY
数据类型不同。后者类型的 BINARY
属性不将列视为二进制字符串列,而是使该列使用二进制(_bin
) 字符集(或如果未指定列字符集,则使用表默认字符集)并将列本身存储非二进制字符字符串,而不是二进制字节字符串。例如,如果默认字符集为 utf8mb4
,CHAR(5) BINARY
将被视为 CHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
。这与 BINARY(5)
不同,它存储 5 个字节的二进制字符串,该字符集和排序规则为 binary
。关于 binary
字符集的排序规则与非二进制字符集的 _bin 排序规则之间的差异,见第 12.8.5 节,“The binary Collation Compared to _bin Collations”。
如果不启用严格 SQL 模式,并将值分配给 BINARY
或 VARBINARY
列,且该值超过列的最大长度,则该值将被截断以适应并生成警告。要在截断情况下引发错误,而不是警告,并抑制插入该值,请启用严格 SQL 模式。见第 7.1.11 节,“Server SQL Modes”。
当存储BINARY
值时,它们将被右对齐到指定的长度,填充值为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
数据类型存储二进制数据,并且需要检索的值与存储的值完全相同,那么就需要小心考虑前置填充和去除特性。以下示例展示了0x00
-填充对BINARY
值比较的影响:
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
数据类型之一。
在mysql客户端,二进制字符串使用十六进制表示,取决于--binary-as-hex
的值。关于该选项的更多信息,请参见第6.5.1节,“mysql — The MySQL Command-Line Client”.