# 10.10.1 Unicode 字符集

本节介绍可用于 Unicode 字符集的排序规则及其区分属性。有关 Unicode 的一般信息,请参阅第 10.9 节,“Unicode 支持”.

MySQL 支持多种 Unicode 字符集:

  • utf8mb4: Unicode 字符集的 UTF-8 编码,每个字符使用一到四个字节。

  • utf8mb3: Unicode 字符集的 UTF-8 编码,每个字符使用一到三个字节。

  • utf8: 的别名utf8mb3.

  • ucs2: Unicode 字符集的 UCS-2 编码,每个字符使用两个字节。在 MySQL 8.0.28 中已弃用;期望在 MySQL 的未来版本中删除对这个字符集的支持。

  • utf16: Unicode 字符集的 UTF-16 编码,每个字符使用两个或四个字节。喜欢ucs2但带有补充字符的扩展名。

  • utf16le:Unicode 字符集的 UTF-16LE 编码。喜欢utf16但小端而不是大端。

  • utf32: Unicode 字符集的 UTF-32 编码,每个字符使用四个字节。

笔记

utf8mb3不推荐使用字符集,您应该期望它在未来的 MySQL 版本中被删除。请用utf8mb4反而。utf8目前是一个别名utf8mb3, 但它现在已被弃用,并且utf8预计随后将成为参考utf8mb4.从 MySQL 8.0.28 开始,utf8mb3也显示在utf8在信息模式表的列中,以及在 SQL 的输出中显示陈述。

为了避免含义模糊utf8,考虑指定utf8mb4明确地用于字符集引用。

utf8mb4,utf16,utf16le, 和utf32支持基本多语言平面 (BMP) 字符和位于 BMP 之外的补充字符。utf8ucs2仅支持 BMP 字符。

大多数 Unicode 字符集都有一个通用排序规则(由_一般的在名称中或没有语言说明符),二进制排序规则(由_bin在名称中)和几个特定于语言的排序规则(由语言说明符指示)。例如,对于utf8mb4,utf8mb4_general_ciutf8mb4_bin是它的一般和二进制排序规则,并且utf8mb4_danish_ci是其特定于语言的排序规则之一。

大多数字符集都有一个二进制排序规则。utf8mb4是一个例外,有两个:utf8mb4_bin和(从 MySQL 8.0.17 开始)utf8mb4_0900_bin.这两个二进制归类具有相同的排序顺序,但通过它们的填充属性和归类权重特性来区分。看整理垫属性, 和字符整理权重.

校对支持utf16le是有限的。唯一可用的排序规则是utf16le_general_ciutf16le_bin.这些类似于utf16_general_ciutf16_bin.

# Unicode 排序算法 (UCA) 版本

MySQL 实现了*xxx*_unicode_ci根据 Unicode Collat​​ion Algorithm (UCA) 描述的排序规则http://www.unicode.org/reports/tr10/ (opens new window).排序规则使用版本 4.0.0 UCA 权重键:http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt (opens new window).这*xxx*_unicode_ci排序规则仅部分支持 Unicode 排序算法。不支持某些字符,也不完全支持组合标记。这会影响越南语、约鲁巴语和纳瓦霍语等语言。在字符串比较中,组合字符被认为与用单个 unicode 字符编写的相同字符不同,并且这两个字符被认为具有不同的长度(例如,由CHAR_LENGTH()函数或结果集元数据)。

基于高于 4.0.0 的 UCA 版本的 Unicode 排序规则在排序规则名称中包含该版本。例子:

# 整理垫属性

基于 UCA 9.0.0 和更高版本的排序规则比基于 9.0.0 之前的 UCA 版本的排序规则更快。它们还具有 pad 属性无垫, 与焊盘空间用于基于 9.0.0 之前的 UCA 版本的排序规则。为了比较非二进制字符串,无垫排序规则将字符串末尾的空格视为任何其他字符(请参阅比较中的尾随空间处理)。

要确定排序规则的填充属性,请使用INFORMATION_SCHEMA 校对表,其中有一个PAD_ATTRIBUTE柱子。例如:

mysql> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE CHARACTER_SET_NAME = 'utf8mb4';
+----------------------------+---------------+
| COLLATION_NAME             | PAD_ATTRIBUTE |
+----------------------------+---------------+
| utf8mb4_general_ci         | PAD SPACE     |
| utf8mb4_bin                | PAD SPACE     |
| utf8mb4_unicode_ci         | PAD SPACE     |
| utf8mb4_icelandic_ci       | PAD SPACE     |
...
| utf8mb4_0900_ai_ci         | NO PAD        |
| utf8mb4_de_pb_0900_ai_ci   | NO PAD        |
| utf8mb4_is_0900_ai_ci      | NO PAD        |
...
| utf8mb4_ja_0900_as_cs      | NO PAD        |
| utf8mb4_ja_0900_as_cs_ks   | NO PAD        |
| utf8mb4_0900_as_ci         | NO PAD        |
| utf8mb4_ru_0900_ai_ci      | NO PAD        |
| utf8mb4_ru_0900_as_cs      | NO PAD        |
| utf8mb4_zh_0900_as_cs      | NO PAD        |
| utf8mb4_0900_bin           | NO PAD        |
+----------------------------+---------------+

非二进制字符串值的比较 (字符,VARCHAR, 和文本) 有一个无垫排序规则与其他排序规则在尾随空格方面不同。例如,'一种''一种 '比较为不同的字符串,而不是相同的字符串。这可以使用二进制排序规则看到utf8mb4.pad 属性为utf8mb4_bin焊盘空间, 而对于utf8mb4_0900_bin它是无垫.因此,涉及的操作utf8mb4_0900_bin不要添加尾随空格,并且对于两个排序规则,涉及带有尾随空格的字符串的比较可能会有所不同:

mysql> CREATE TABLE t1 (c CHAR(10) COLLATE utf8mb4_bin);
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t1 VALUES('a');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM t1 WHERE c = 'a ';
+------+
| c    |
+------+
| a    |
+------+
1 row in set (0.00 sec)

mysql> ALTER TABLE t1 MODIFY c CHAR(10) COLLATE utf8mb4_0900_bin;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t1 WHERE c = 'a ';
Empty set (0.00 sec)

# 语言特定的排序规则

如果仅基于 Unicode 排序算法 (UCA) 的排序不适用于一种语言,则 MySQL 实现特定于语言的 Unicode 排序规则。特定于语言的排序规则是基于 UCA 的,具有额外的语言定制规则。此类规则的示例将在本节后面出现。有关特定语言排序的问题,unicode.org提供 Common Locale Data Repository (CLDR) 整理图表http://www.unicode.org/cldr/charts/30/collat​​ion/index.html (opens new window).

例如,非语言特定的utf8mb4_0900_ai_ci和特定语言utf8mb4_*语言环境*_0900_ai_ciUnicode 排序规则各自具有以下特征:

  • 排序规则基于 UCA 9.0.0 和 CLDR v30,不区分重音和大小写。这些特征由_0900,_ai, 和_ci在排序规则名称中。例外:utf8mb4_la_0900_ai_ci不是基于 CLDR,因为 CLDR 中没有定义古典拉丁语。

  • 排序规则适用于范围内的所有字符[U+0, U+10FFFF].

  • 如果排序规则不是特定于语言的,它将按默认顺序对所有字符(包括补充字符)进行排序(如下所述)。如果排序规则是特定于语言的,它会根据特定于语言的规则正确排序语言的字符,而不是默认顺序的语言中的字符。

  • 默认情况下,排序规则根据表中分配的权重值对具有 DUCET 表(默认 Unicode 排序元素表)中列出的代码点的字符进行排序。排序规则使用根据 UCA 构造的隐式权重值对 DUCET 表中没有列出代码点的字符进行排序。

  • 对于非语言特定的排序规则,收缩序列中的字符被视为单独的字符。对于特定于语言的排序规则,缩写可能会更改字符排序顺序。

    包含下表中显示的区域设置代码或语言名称的排序规则名称是特定于语言的排序规则。Unicode 字符集可能包括一种或多种这些语言的排序规则。

表 10.3 Unicode 排序语言说明符

语言 语言说明符
中国人 zh
古典拉丁语 要么罗马的
克罗地亚语 小时要么克罗地亚人
捷克语 cs要么捷克语
丹麦语 要么丹麦语
世界语 要么世界语
爱沙尼亚语 要么爱沙尼亚语
德国电话簿订单 de_pb要么德语2
匈牙利 要么匈牙利
冰岛的 要么冰岛的
日本人
拉脱维亚语 lv要么拉脱维亚语
立陶宛语 lt要么立陶宛语
波斯语 波斯语
抛光 要么抛光
罗马尼亚语 要么罗马尼亚语
俄语
僧伽罗语 僧伽罗语
斯洛伐克语 sk要么斯洛伐克语
斯洛文尼亚语 sl要么斯洛文尼亚语
现代西班牙语 es要么西班牙语
传统西班牙语 es_trad要么西班牙语2
瑞典 sv要么瑞典
土耳其 tr要么土耳其
越南语 要么越南语

克罗地亚语排序规则是为这些克罗地亚语字母量身定制的:C,C,Dz,Đ,Lj,新泽西州,Š,Ž.

丹麦语排序规则也可用于挪威语。

对于日本人来说,utf8mb4字符集包括utf8mb4_ja_0900_as_csutf8mb4_ja_0900_as_cs_ks排序规则。两种排序规则都区分重音和区分大小写。utf8mb4_ja_0900_as_cs_ks也是假名敏感的,并将片假名字符与平假名字符区分开来,而utf8mb4_ja_0900_as_cs将片假名和平假名字符视为相同的排序。需要日语排序但不需要假名敏感性的应用程序可以使用utf8mb4_ja_0900_as_cs以获得更好的排序性能。utf8mb4_ja_0900_as_cs使用三个重量级别进行排序;utf8mb4_ja_0900_as_cs_ks使用四个。

对于不区分重音的古典拉丁语排序规则,一世Ĵ比较相等,并且ü比较相等。一世Ĵ, 和ü在基本字母级别上进行比较。换一种说法,Ĵ被视为重音一世, 和ü被视为重音.

西班牙语排序规则可用于现代和传统西班牙语。对彼此而言,ñ(n-波浪号) 是一个单独的字母n.此外,对于传统的西班牙语,ch是一个单独的字母cd, 和是一个单独的字母l.

传统的西班牙排序规则也可用于阿斯图里亚斯语和加利西亚语。

瑞典排序规则包括瑞典规则。例如,在瑞典语中,以下关系成立,这不是说德语或法语的人所期望的:

Ü = Y < Ö

# _一般的_词对_统一码_ci 校对

对于任何 Unicode 字符集,使用*xxx*_general_ci整理比那些为快*xxx*_unicode_ci整理。例如,比较utf8_general_ci排序比比较更快,但正确性稍差utf8_unicode_ci.原因是utf8_unicode_ci支持扩展等映射;也就是说,当一个字符比较等于其他字符的组合时。例如,ß等于ss德语和其他一些语言。utf8_unicode_ci还支持缩写和可忽略的字符。utf8_general_ci是不支持扩展、收缩或可忽略字符的遗留排序规则。它只能在字符之间进行一对一的比较。

为了进一步说明,以下等式在两者中都成立utf8_general_ciutf8_unicode_ci(对于比较或搜索中的效果,请参阅第 10.8.6 节,“整理效果示例”):

Ä = A
Ö = O
Ü = U

排序规则之间的区别在于,对于utf8_general_ci

ß = s

而这对于utf8_unicode_ci,它支持德语 DIN-1 排序(也称为字典排序):

ß = ss

MySQL 实现utf8语言特定的排序规则,如果使用utf8_unicode_ci不适用于一种语言。例如,utf8_unicode_ci适用于德语字典顺序和法语,因此无需创建特殊的utf8排序规则。

utf8_general_ci对德语和法语也都满意,除了ß等于s,而不是ss.如果这对您的应用程序是可以接受的,您应该使用utf8_general_ci因为它更快。如果这是不可接受的(例如,如果您需要德语字典顺序),请使用utf8_unicode_ci因为它更准确。

如果您需要德国 DIN-2(电话簿)订购,请使用utf8_german2_ci排序规则,它比较以下字符集是否相等:

Ä = Æ = AE
Ö = Œ = OE
Ü = UE
ß = ss

utf8_german2_ci类似于latin1_german2_ci, 但后者不比较Æ等于AE要么Œ等于OE.没有utf8_german_ci对应于latin1_german_ci对于德语字典顺序,因为utf8_general_ci就够了。

# 字符整理权重

字符的整理权重确定如下:

  • 对于所有 Unicode 排序规则,除了_bin(二进制)排序规则,MySQL 执行表查找以查找字符的排序规则。

  • 为了_bin排序规则除了utf8mb4_0900_bin,权重基于代码点,可能添加了前导零字节。

  • 为了utf8mb4_0900_bin,权重为utf8mb4编码字节。排序顺序与 for 相同utf8mb4_bin,但要快得多。

    整理权重可以使用重量字符串()功能。(看第 12.8 节,“字符串函数和运算符”.) 如果排序规则使用权重查找表,但表中没有字符(例如,因为它是“新”字符),则排序规则确定权重变得更加复杂:

  • 对于一般排序规则中的 BMP 字符 (*xxx*_general_ci),权重是码点。

  • 对于 UCA 归类中的 BMP 字符(例如,*xxx*_unicode_ci和特定于语言的排序规则),以下算法适用:

    if (code >= 0x3400 && code <= 0x4DB5)
      base= 0xFB80; /* CJK Ideograph Extension */
    else if (code >= 0x4E00 && code <= 0x9FA5)
      base= 0xFB40; /* CJK Ideograph */
    else
      base= 0xFBC0; /* All other characters */
    aaaa= base +  (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;
    

    结果是两个整理元素的序列,啊啊啊其次是bbbb.例如:

    mysql> SELECT HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci));
    +----------------------------------------------------------+
    | HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci)) |
    +----------------------------------------------------------+
    | FBC084CF                                                 |
    +----------------------------------------------------------+
    

    因此,U+04cf 西里尔小写字母 PALOCHKA是,对于所有 UCA 4.0.0 排序规则,大于U+04c0 西里尔字母 PALOCHKA.使用 UCA 5.2.0 排序规则,所有 palochka 排序在一起。

  • 对于一般校对中的补充字符,权重是0xfffd 替换字符.对于 UCA 4.0.0 归类中的补充字符,它们的归类权重为0xfffd.也就是说,对于 MySQL 来说,所有的补充字符都是相等的,并且大于几乎所有的 BMP 字符。

    一个带有 Deseret 字符的示例和计数(不同)

    CREATE TABLE t (s1 VARCHAR(5) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0xfffd);   /* REPLACEMENT CHARACTER */
    INSERT INTO t VALUES (0x010412); /* DESERET CAPITAL LETTER BEE */
    INSERT INTO t VALUES (0x010413); /* DESERET CAPITAL LETTER TEE */
    SELECT COUNT(DISTINCT s1) FROM t;
    

    结果是 2 因为在 MySQL*xxx*_unicode_ci排序规则,替换字符的权重为0x0dc6,而 Deseret Bee 和 Deseret Tee 的重量均为0xfffd.(是utf32_general_ci使用排序规则,结果为 1,因为所有三个字符的权重为0xfffd在该排序规则中。)

    楔形文字的例子和重量字符串()

    /*
    The four characters in the INSERT string are
    00000041  # LATIN CAPITAL LETTER A
    0001218F  # CUNEIFORM SIGN KAB
    000121A7  # CUNEIFORM SIGN KISH
    00000042  # LATIN CAPITAL LETTER B
    */
    CREATE TABLE t (s1 CHAR(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0x000000410001218f000121a700000042);
    SELECT HEX(WEIGHT_STRING(s1)) FROM t;
    

    结果是:

    0E33 FFFD FFFD 0E4A
    

    0E330E4A主要重量是否如中所示UCA 4.0.0.FFFD是KAB和KISH的重量。

    所有补充字符都相等的规则是非最优的,但预计不会造成问题。这些字符非常罕见,因此多字符字符串完全由补充字符组成的情况非常罕见。在日本,由于补充字符是晦涩难懂的汉字,典型的用户无论如何都不在乎它们的顺序。如果您真的希望行按MySQL规则排序,然后按代码点值排序,那么很简单:

    ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
    
  • 对于基于高于4.0.0的UCA版本的补充字符(例如,*xxx*_unicode_520_ci),补充字符不一定都具有相同的排序权重。有些人有来自UCA的明确权重所有人。txt文件其他人则使用此算法计算权重:

    aaaa= base +  (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;
    

“按字符的代码值排序”和“按字符的二进制表示排序”之间存在差异,这种差异仅在utf16_bin因为代孕妈妈。

假设utf16_bin(用于utf16)是“逐字节”的二进制比较,而不是“逐字符”的二进制比较如果是这样的话,字符的顺序utf16_bin与订单不同utf8_bin.例如,下图显示了两个罕见的字符。第一个字符在范围内E000-FFFF,所以它比替代品大,但比补充品小。第二个字符是补充字符。

Code point  Character                    utf8         utf16
----------  ---------                    ----         -----
0FF9D       HALFWIDTH KATAKANA LETTER N  EF BE 9D     FF 9D
10384       UGARITIC LETTER DELTA        F0 90 8E 84  D8 00 DF 84

图表中的两个字符按代码点值排列,因为0xff9d\<0x10384. And they are in order byutf8value because0xef\<0xf0. But they are not in order byutf16value, if we use byte-by-byte comparison, because0xff > 0xd8.

So MySQL'sutf16_bincollation is not “byte by byte.” It is “by code point.” When MySQL sees a supplementary-character encoding inutf16, it converts to the character's code-point value, and then compares. Therefore,utf8_binandutf16_binare the same ordering. This is consistent with the SQL:2008 standard requirement for a UCS_BASIC collation: “UCS_BASIC is a collation in which the ordering is determined entirely by the Unicode scalar values of the characters in the strings being sorted. It is applicable to the UCS character repertoire. Since every character repertoire is a subset of the UCS repertoire, the UCS_基本排序规则可能适用于每个字符集。注11:字符的Unicode标量值是其被视为无符号整数的代码点。”

如果字符集是ucs2,比较是逐字节的,但是ucs2无论如何,字符串不应该包含代理项。

# 杂项信息

这个*xxx*_通用mysql500排序规则保留了5.1.24之前的原始顺序*xxx*_尤奇将军对MySQL 5.1.24(Bug#27877)之前创建的表进行排序并允许升级。