# 10.8.5 二进制排序规则比较_分类整理

本节介绍如何二进制二进制字符串的排序规则比较_bin非二进制字符串的排序规则。

二进制字符串(使用二进制,变量, 和斑点数据类型)有一个字符集和排序规则命名二进制.二进制字符串是字节序列,这些字节的数值决定了比较和排序顺序。看第 10.10.8 节,“二进制字符集”.

非二进制字符串(使用字符,VARCHAR, 和文本数据类型)具有字符集和排序规则,而不是二进制.给定的非二进制字符集可以有多个排序规则,每个排序规则都定义了集合中字符的特定比较和排序顺序。对于大多数字符集,其中之一是二进制排序规则,由_bin排序规则名称中的后缀。例如,二进制排序规则utf8拉丁语1被称为utf8_binlatin1_bin, 分别。utf8mb4是具有两个二进制排序规则的异常,utf8mb4_binutf8mb4_0900_bin;看第 10.10.1 节,“Unicode 字符集”.

二进制排序规则不同于_bin在以下几节中讨论了几个方面的排序规则:

# 比较排序单元

二进制字符串是字节序列。为了二进制排序、比较和排序基于数字字节值。非二进制字符串是字符序列,可能是多字节的。非二进制字符串的排序规则定义了用于比较和排序的字符值的顺序。为了_bin排序规则,此排序基于数字字符代码值,这类似于二进制字符串的排序,只是字符代码值可能是多字节的。

# 字符集转换

非二进制字符串有一个字符集,并且在很多情况下会自动转换为另一个字符集,即使该字符串有一个_bin整理:

  • 将列值分配给具有不同字符集的另一列时:

    UPDATE t1 SET utf8_bin_column=latin1_column;
    INSERT INTO t1 (latin1_column) SELECT utf8_bin_column FROM t2;
    
  • 分配列值时插入要么更新使用字符串文字:

    SET NAMES latin1;
    INSERT INTO t1 (utf8_bin_column) VALUES ('string-in-latin1');
    
  • 从服务器向客户端发送结果时:

    SET NAMES latin1;
    SELECT utf8_bin_column FROM t2;
    

    对于二进制字符串列,不会发生转换。对于与前面类似的情况,字符串值是按字节复制的。

# 字母大小写转换

非二进制字符集的排序规则提供有关字符字母大小写的信息,因此非二进制字符串中的字符可以从一种字母大小写转换为另一种字母大小写,即使对于_bin排序忽略字母大小写的排序规则:

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
mysql> SELECT LOWER('aA'), UPPER('zZ');
+-------------+-------------+
| LOWER('aA') | UPPER('zZ') |
+-------------+-------------+
| aa          | ZZ          |
+-------------+-------------+

字母大小写的概念不适用于二进制字符串中的字节。要执行字母大小写转换,必须首先使用适合存储在字符串中的数据的字符集将字符串转换为非二进制字符串:

mysql> SET NAMES binary;
mysql> SELECT LOWER('aA'), LOWER(CONVERT('aA' USING utf8mb4));
+-------------+------------------------------------+
| LOWER('aA') | LOWER(CONVERT('aA' USING utf8mb4)) |
+-------------+------------------------------------+
| aA          | aa                                 |
+-------------+------------------------------------+

# 比较中的尾随空间处理

MySQL 排序规则有一个 pad 属性,其值为焊盘空间要么无垫

  • 大多数 MySQL 排序规则都有一个 pad 属性焊盘空间.

  • 基于 UCA 9.0.0 及更高版本的 Unicode 归类具有填充属性无垫;看第 10.10.1 节,“Unicode 字符集”.

    对于非二进制字符串 (字符,VARCHAR, 和文本值),字符串排序规则填充属性确定在比较字符串末尾的尾随空格时的处理方式:

  • 为了焊盘空间排序规则,尾随空格在比较中是微不足道的;比较字符串时不考虑尾随空格。

  • 无垫排序规则将尾随空格视为重要的比较,就像任何其他字符一样。

    不同的行为可以使用这两个来演示utf8mb4二进制排序规则,其中之一是焊盘空间, 另一个是无垫.该示例还显示了如何使用INFORMATION_SCHEMA 校对表来确定排序规则的填充属性。

mysql> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE COLLATION_NAME LIKE 'utf8mb4%bin';
+------------------+---------------+
| COLLATION_NAME   | PAD_ATTRIBUTE |
+------------------+---------------+
| utf8mb4_bin      | PAD SPACE     |
| utf8mb4_0900_bin | NO PAD        |
+------------------+---------------+
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
mysql> SELECT 'a ' = 'a';
+------------+
| 'a ' = 'a' |
+------------+
|          1 |
+------------+
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_bin;
mysql> SELECT 'a ' = 'a';
+------------+
| 'a ' = 'a' |
+------------+
|          0 |
+------------+

笔记

本文中的“比较”不包括喜欢模式匹配运算符,无论排序规则如何,尾随空格都很重要。

对于二进制字符串 (二进制,变量, 和斑点值),所有字节在比较中都很重要,包括尾随空格:

mysql> SET NAMES binary;
mysql> SELECT 'a ' = 'a';
+------------+
| 'a ' = 'a' |
+------------+
|          0 |
+------------+

# 插入和检索的尾随空间处理

字符(*ñ*)列存储非二进制字符串*ñ长字符。对于插入,值短于ñ*字符用空格扩展。对于检索,删除尾随空格。

二进制(*ñ*)列存储二进制字符串*ñ字节长。对于插入,值短于ñ*字节扩展为0x00字节。对于检索,不会删除任何内容;始终返回声明长度的值。

mysql> CREATE TABLE t1 (
         a CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin,
         b BINARY(10)
       );
mysql> INSERT INTO t1 VALUES ('x','x');
mysql> INSERT INTO t1 VALUES ('x ','x ');
mysql> SELECT a, b, HEX(a), HEX(b) FROM t1;
+------+------------+--------+----------------------+
| a    | b          | HEX(a) | HEX(b)               |
+------+------------+--------+----------------------+
| x    | x          | 78     | 78000000000000000000 |
| x    | x          | 78     | 78200000000000000000 |
+------+------------+--------+----------------------+