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)
有关实现说明,请参阅 第 12.14.3 节,“向 8 位字符集添加简单校对规则”。
8 位字符集的复杂校对规则
这种校对规则使用 C 源文件中的函数实现,这些函数定义了如何对字符进行排序,如 第 12.13 节,“添加字符集” 中所述。
非 Unicode 多字节字符集的校对规则
对于这种类型的校对规则,8 位(单字节)和多字节字符的处理方式不同。对于 8 位字符,字符代码以不区分大小写的方式映射到权重。(例如,单字节字符 'a'
和 'A'
的权重均为 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)
有关实现说明,请参阅 第 12.13 节,“添加字符集”。
Unicode 多字节字符集的校对规则
其中一些校对规则基于 Unicode 校对算法 (UCA),而另一些则不是。
非 UCA 校对规则具有从字符代码到权重的一对一映射。在 MySQL 中,此类校对规则不区分大小写和重音。 utf8mb4_general_ci
就是一个例子:'a'
、'A'
、'À'
和 'á'
都有不同的字符代码,但权重都为 0x0041
,比较结果相等。
mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_general_ci';
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1
(c1 CHAR(1) CHARACTER SET UTF8MB4 COLLATE utf8mb4_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" 没有权重,可以忽略。
一个字符可能有一个权重。例如:
'a'
的权重为0x0E33
。mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_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 连字,或 SHARP S)的权重为0x0FEA0FEA
。mysql> SET NAMES 'utf8mb4' COLLATE 'utf8mb4_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 'utf8mb4' COLLATE 'utf8mb4_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 校对规则,请参阅 第 12.13 节,“添加字符集”。对于 UCA 校对规则,请参阅 第 12.14.4 节,“向 Unicode 字符集添加 UCA 校对规则”。
其他校对规则
还有一些校对规则不属于上述任何类别。