### 10.14.1 排序规则实现类型

MySQL 实现了几种类型的排序规则：

**8 位字符集的简单排序规则**

这种排序是使用一个包含 256 个权重的数组来实现的，该数组定义了从字符代码到权重的一对一映射。`latin1_swedish_ci`是一个例子。它是不区分大小写的排序规则，因此字符的大写和小写版本具有相同的权重并且它们比较相等。

```
mysql> SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT HEX(WEIGHT_STRING('a')), HEX(WEIGHT_STRING('A'));
+-------------------------+-------------------------+
| HEX(WEIGHT_STRING('a')) | HEX(WEIGHT_STRING('A')) |
+-------------------------+-------------------------+
| 41                      | 41                      |
+-------------------------+-------------------------+
1 row in set (0.01 sec)

mysql> SELECT 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
|         1 |
+-----------+
1 row in set (0.12 sec)
```

有关实施说明，请参阅[第 10.14.3 节，“向 8 位字符集添加简单排序规则”](adding-collation-simple-8bit.html).

**8 位字符集的复杂排序规则**

这种排序规则是使用 C 源文件中的函数实现的，这些函数定义了如何对字符进行排序，如中所述[第 10.13 节，“添加字符集”](adding-character-set.html).

**非 Unicode 多字节字符集的排序规则**

对于这种排序规则，8 位（单字节）和多字节字符的处理方式不同。对于 8 位字符，字符代码以不区分大小写的方式映射到权重。（例如，单字节字符`'一种'`和`'一种'`两者的重量均为`0x41`.) 对于多字节字符，字符代码和权重之间有两种关系：

-   权重等于字符代码。`sjis_japanese_ci`是这种排序规则的一个例子。多字节字符`'ぢ'`有一个字符代码`0x82C0`, 权重也是`0x82C0`.

    ```
    mysql> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET sjis COLLATE sjis_japanese_ci);
    Query OK, 0 rows affected (0.01 sec)

    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x82C0);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0

    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    +------+---------+------------------------+
    | c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a    | 61      | 41                     |
    | A    | 41      | 41                     |
    | ぢ    | 82C0    | 82C0                   |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)
    ```

-   字符代码与权重一一对应，但代码不一定等于权重。`gbk_chinese_ci`是这种排序规则的一个例子。多字节字符`'膰'`有一个字符代码`0x81B0`但重量`0xC286`.

    ```
    mysql> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET gbk COLLATE gbk_chinese_ci);
    Query OK, 0 rows affected (0.33 sec)

    mysql> INSERT INTO t1 VALUES ('a'),('A'),(0x81B0);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0

    mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    +------+---------+------------------------+
    | c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
    +------+---------+------------------------+
    | a    | 61      | 41                     |
    | A    | 41      | 41                     |
    | 膰    | 81B0    | C286                   |
    +------+---------+------------------------+
    3 rows in set (0.00 sec)
    ```

    有关实施说明，请参阅[第 10.13 节，“添加字符集”](adding-character-set.html).

**Unicode 多字节字符集的排序规则**

其中一些排序规则基于 Unicode 排序算法 (UCA)，而其他排序规则则不是。

非 UCA 归类具有从字符代码到权重的一对一映射。在 MySQL 中，此类排序规则不区分大小写和重音。`utf8_general_ci`是一个例子：`'一种'`,`'一种'`,`'一种'`， 和`'一种'`每个都有不同的字符代码，但都有一个权重`0x0041`并比较相等。

```
mysql> SET NAMES 'utf8' COLLATE 'utf8_general_ci';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t1
       (c1 CHAR(1) CHARACTER SET UTF8 COLLATE utf8_general_ci);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t1 VALUES ('a'),('A'),('À'),('á');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
+------+---------+------------------------+
| c1   | HEX(c1) | HEX(WEIGHT_STRING(c1)) |
+------+---------+------------------------+
| a    | 61      | 0041                   |
| A    | 41      | 0041                   |
| À    | C380    | 0041                   |
| á    | C3A1    | 0041                   |
+------+---------+------------------------+
4 rows in set (0.00 sec)
```

MySQL 中基于 UCA 的排序规则具有以下属性：

-   如果一个字符有权重，每个权重使用 2 个字节（16 位）。

-   一个角色可能有零权重（或空权重）。在这种情况下，字符是可忽略的。示例：“U+0000 NULL”没有权重，可以忽略。

-   一个角色可能有一个权重。例子：`'一种'`重量为`0x0E33`.

    ```
    mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';
    Query OK, 0 rows affected (0.05 sec)

    mysql> SELECT HEX('a'), HEX(WEIGHT_STRING('a'));
    +----------+-------------------------+
    | HEX('a') | HEX(WEIGHT_STRING('a')) |
    +----------+-------------------------+
    | 61       | 0E33                    |
    +----------+-------------------------+
    1 row in set (0.02 sec)
    ```

-   一个角色可能有很多权重。这是一个扩展。示例：德语字母`'ß'`（SZ ligature，或 SHARP S）的重量为`0x0FEA0FEA`.

    ```
    mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';
    Query OK, 0 rows affected (0.11 sec)

    mysql> SELECT HEX('ß'), HEX(WEIGHT_STRING('ß'));
    +-----------+--------------------------+
    | HEX('ß')  | HEX(WEIGHT_STRING('ß'))  |
    +-----------+--------------------------+
    | C39F      | 0FEA0FEA                 |
    +-----------+--------------------------+
    1 row in set (0.00 sec)
    ```

-   许多字符可能有一个权重。这是一种收缩。例子：`'ch'`是捷克语中的一个字母，重量为`0x0EE2`.

    ```
    mysql> SET NAMES 'utf8' COLLATE 'utf8_czech_ci';
    Query OK, 0 rows affected (0.09 sec)

    mysql> SELECT HEX('ch'), HEX(WEIGHT_STRING('ch'));
    +-----------+--------------------------+
    | HEX('ch') | HEX(WEIGHT_STRING('ch')) |
    +-----------+--------------------------+
    | 6368      | 0EE2                     |
    +-----------+--------------------------+
    1 row in set (0.00 sec)
    ```

    多字符到多权重的映射也是可能的（这是收缩与扩展），但 MySQL 不支持。

    有关实现说明，对于非 UCA 排序规则，请参阅[第 10.13 节，“添加字符集”](adding-character-set.html).对于 UCA 归类，请参阅[第 10.14.4 节，“将 UCA 归类添加到 Unicode 字符集”](adding-collation-unicode-uca.html).

**其他排序规则**

还有一些排序规则不属于前面的任何类别。
