BINARYVARBINARY类型与CHARVARCHAR类似,不同之处是它们存储的是二进制字符串而不是非二进制字符串。也就是说,它们存储的是字节字符串而不是字符字符串。这意味着它们具有二进制字符集和排序规则,比较和排序基于值中字节的数值。

BINARYVARBINARY允许的最大长度与CHARVARCHAR相同,不同的是BINARYVARBINARY的长度是以字节而不是字符来度量的。

BINARYVARBINARY数据类型不同于CHAR BINARYVARCHAR 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 模式,并且将超过列最大长度的值分配给BINARYVARBINARY列,该值会被截断以适合列的最大长度,并生成警告。要禁止非空格字符的截断,可以使用严格的 SQL 模式导致出现错误(而不是警告)并禁止插入值。参见 5.1.11 服务器 SQL 模式。

当存储BINARY值时,它们将被右填充为指定长度的填充值。pad 值是0x00(零字节)。值在插入时用0x00右填充,检索时不删除尾随字节。所有的字节在比较中都是重要的,包括ORDER BYDISTINCT操作。0x00和空格在比较时是不同的,0x00在空格之前排序。

例如:对于一个BINARY(3)列,'a '在插入时变成'a \0''a\0'在插入时变成'a\0\0'。两个插入的值在检索时都保持不变。

对于VARBINARY,插入时没有填充,检索时也没有字节剥离。所有的字节在比较中都是重要的,包括ORDER BYDISTINCT操作。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数据类型。