BINARY
和 VARBINARY
类型类似于 CHAR
和 VARCHAR
,区别在于它们存储的是二进制字符串而不是非二进制字符串。也就是说,它们存储的是字节字符串而不是字符字符串。这意味着它们具有 binary
字符集和排序规则,并且比较和排序基于值中字节的数值。
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)
不同,后者存储 5 字节的二进制字符串,这些字符串具有 binary
字符集和排序规则。有关 binary
字符集的 binary
排序规则与非二进制字符集的 _bin
排序规则之间的差异的信息,请参见 第 12.8.5 节“二进制排序规则与 _bin 排序规则的比较”.
如果未启用严格 SQL 模式,并且您将超过列最大长度的值分配给 BINARY
或 VARBINARY
列,则该值将被截断以适应,并会生成警告。对于截断情况,要使错误发生(而不是警告)并抑制值的插入,请使用严格 SQL 模式。请参见 第 7.1.11 节“服务器 SQL 模式”.
当存储 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
数据类型存储二进制数据,并且您要求检索到的值与存储的值完全相同,那么您应该仔细考虑上述填充和删除特性。以下示例说明了 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
数据类型。
在 mysql 客户端中,二进制字符串使用十六进制表示法显示,具体取决于 --binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节“mysql — MySQL 命令行客户端”.