Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

12.10.1 Unicode 字符集

本节描述了 Unicode 字符集的可用排序规则及其区别特性。有关 Unicode 的一般信息,请参阅 第 12.9 节,“Unicode 支持”

MySQL 支持多种 Unicode 字符集:

  • utf8mb4:使用 1 到 4 个字节 per 字符的 Unicode 字符集的 UTF-8 编码。

  • utf8mb3:使用 1 到 3 个字节 per 字符的 Unicode 字符集的 UTF-8 编码。此字符集已弃用;请使用 utf8mb4 代替。

  • utf8:一个弃用的别名为 utf8mb3。请使用 utf8mb4 代替。

    Note

    utf8 预计在未来版本中将成为 utf8mb4 的别名。

  • ucs2:Unicode 字符集的 UCS-2 编码,使用 2 个字节 per 字符。弃用;预计在未来版本中删除对该字符集的支持。

  • utf16:Unicode 字符集的 UTF-16 编码,使用 2 或 4 个字节 per 字符。类似于 ucs2,但具有补充字符的扩展。

  • utf16le:Unicode 字符集的 UTF-16LE 编码。类似于 utf16,但小端序而不是大端序。

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

Note

字符集 utf8mb3 已弃用,您应该期望在未来 MySQL 版本中删除它。请使用 utf8mb4 代替。utf8 目前是 utf8mb3 的别名,但它现在已弃用,utf8 预计将来将成为 utf8mb4 的引用。utf8mb3 也将在信息模式表的列和 SQL SHOW 语句的输出中显示为 utf8

为了避免关于 utf8 的歧义,请考虑明确指定 utf8mb4 作为字符集引用。

utf8mb4utf16utf16leutf32 支持基本多语言平面(BMP)字符和超出 BMP 的补充字符。utf8mb3ucs2 只支持 BMP 字符。

大多数 Unicode 字符集都有一个通用排序(在名称中以 _general 指示或没有语言指定符),一个二进制排序(在名称中以 _bin 指示),以及多种语言特定的排序(以语言指定符指示)。例如,对于 utf8mb4utf8mb4_general_ciutf8mb4_bin 是其通用和二进制排序,而 utf8mb4_danish_ci 是其语言特定排序之一。

大多数字符集只有一个二进制排序。utf8mb4 是一个例外,它有两个:utf8mb4_binutf8mb4_0900_bin。这两个二进制排序具有相同的排序顺序,但它们的填充属性和排序权重特征不同。请参阅 排序填充属性字符排序权重

utf16le 的排序支持有限。只有 utf16le_general_ciutf16le_bin 两个排序可用。它们与 utf16_general_ciutf16_bin 相似。

Unicode 排序算法 (UCA) 版本

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

基于 UCA 高于 4.0.0 版本的 Unicode 排序在排序名称中包括版本。例如:

LOWER()UPPER() 函数根据其参数的排序执行大小写折叠。如果字符只有在 Unicode 版本高于 4.0.0 中才有大写和小写版本,那么这些函数仅在参数排序使用足够高的 UCA 版本时才会转换该字符。

排序填充属性

基于 UCA 9.0.0 及更高版本的排序比基于 UCA 9.0.0 之前的版本排序更快。它们还具有 NO PAD 填充属性,而不是基于 UCA 9.0.0 之前的版本使用的 PAD SPACE。对于非二进制字符串的比较,NO PAD 排序将字符串末尾的空格视为任何其他字符(参见 比较中的尾随空格处理)。

要确定排序的pad属性,请使用 INFORMATION_SCHEMA COLLATIONS 表,该表具有 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        |
+----------------------------+---------------+

非二进制字符串值(CHARVARCHARTEXT)的比较,具有 NO PAD 排序的字符串与其他排序不同,例如,'a''a ' 比较为不同的字符串,而不是相同的字符串。这可以使用 utf8mb4 的二进制排序来看到。utf8mb4_bin 的 pad 属性为 PAD SPACE,而 utf8mb4_0900_bin 的 pad 属性为 NO PAD。因此,涉及 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)

语言特定排序

MySQL 实现语言特定 Unicode 排序,如果仅基于 Unicode 排序算法(UCA)不能很好地工作于语言。语言特定排序基于 UCA,具有附加的语言定制规则。该节后面将出现这些规则的示例。对于特定语言的排序问题,请访问 http://unicode.org,该网站提供公共语言环境数据存储库(CLDR)排序图表:http://www.unicode.org/cldr/charts/30/collation/index.html

例如,非语言特定 utf8mb4_0900_ai_ci 和语言特定 utf8mb4_LOCALE_0900_ai_ci Unicode 排序各具有以下特征:

  • 该排序基于 UCA 9.0.0 和 CLDR v30,是不区分重音和大小写的。这些特征由 _0900_ai_ci 在排序名称中表示。例外:utf8mb4_la_0900_ai_ci 不基于 CLDR,因为古典拉丁语在 CLDR 中未定义。

  • 该排序适用于 Unicode 范围 [U+0, U+10FFFF] 中的所有字符。

  • 如果排序不是语言特定的,则所有字符,包括补充字符,在默认顺序中排序。如果排序是语言特定的,则根据语言特定规则正确地排序语言中的字符,并在默认顺序中排序语言外的字符。

  • 默认情况下,排序将根据 DUCET 表(默认 Unicode 排序元素表)中列出的代码点的权重值进行排序。对于不在 DUCET 表中的代码点,排序将使用隐式权重值,该值根据 UCA 构造。

  • 对于非语言特定的排序,收缩序列中的字符将被视为单个字符。对于语言特定的排序,收缩可能会改变字符的排序顺序。

包含语言代码或语言名称的排序名称是语言特定的排序。 Unicode 字符集可能包括一个或多个语言的排序。

表 12.3 Unicode 排序语言指定符

Language Language Specifier
波斯尼亚语 bs
保加利亚语 bg
中文 zh
古典拉丁语 la 或 roman
克罗地亚语 hr 或 croatian
捷克语 cs 或 czech
丹麦语 da 或 danish
世界语 eo 或 esperanto
爱沙尼亚语 et 或 estonian
加利西亚语 gl
德国电话簿顺序 de_pb 或 german2
匈牙利语 hu 或 hungarian
冰岛语 is 或 icelandic
日语 ja
拉脱维亚语 lv 或 latvian
立陶宛语 lt 或 lithuanian
蒙古语 mn
挪威语 / 书面挪威语 nb
挪威语 / 新挪威语 nn
波斯语 persian
波兰语 pl 或 polish
罗马尼亚语 ro 或 romanian
俄语 ru
塞尔维亚语 sr
僧伽罗语 sinhala
斯洛伐克语 sk 或 斯洛伐克语
斯洛文尼亚语 sl 或 斯洛文尼亚语
现代西班牙语 es 或 西班牙语
传统西班牙语 es_trad 或 西班牙语2
瑞典语 sv 或 瑞典语
土耳其语 tr 或 土耳其语
越南语 vi 或 越南语

MySQL 提供了保加利亚排序规则 utf8mb4_bg_0900_ai_ciutf8mb4_bg_0900_as_cs

克罗地亚排序规则是为克罗地亚字母 ČĆĐLjNjŠŽ 而设计的。

MySQL 提供了塞尔维亚语和波斯尼亚语的拉丁字母排序规则:utf8mb4_sr_latn_0900_ai_ciutf8mb4_sr_latn_0900_as_cs 用于塞尔维亚语,utf8mb4_bs_0900_ai_ciutf8mb4_bs_0900_as_cs 用于波斯尼亚语。

MySQL 提供了挪威语的两种主要变体的排序规则:对于布克莫尔语,可以使用 utf8mb4_nb_0900_ai_ciutf8mb4_nb_0900_as_cs;对于尼诺斯克语,MySQL 现在提供 utf8mb4_nn_0900_ai_ciutf8mb4_nn_0900_as_cs

对于日本语,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 使用四个权重级别。

对于经典拉丁语排序,accent-insensitive,IJ 比较相等,UV 比较相等。IJ,以及 UV 在基本字母级别上比较相等。换言之,J 被视为带音标的 IU 被视为带音标的 V

MySQL 提供了蒙古语 Cyrillic 字符集的排序,utf8mb4_mn_cyrl_0900_ai_ciutf8mb4_mn_cyrl_0900_as_cs

西班牙语排序可用于现代和传统西班牙语。对于这两种,ñ(ñ)是介于 no 之间的独立字母。此外,对于传统西班牙语,ch 是介于 cd 之间的独立字母,ll 是介于 lm 之间的独立字母。

传统西班牙语排序也可以用于阿斯图里亚斯语和加利西亚语。MySQL 还提供了 utf8mb4_gl_0900_ai_ciutf8mb4_gl_0900_as_cs 排序用于加利西亚语。(这些排序与 utf8mb4_es_0900_ai_ciutf8mb4_es_0900_as_cs 相同。)

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

Ü = Y < Ö

_general_ci 与 _unicode_ci 排序

对于任何 Unicode 字符集,使用 xxx_general_ci 排序的操作比使用 xxx_unicode_ci 排序的操作要快。例如,utf8mb4_general_ci 排序的比较比 utf8mb4_unicode_ci 排序的比较要快,但略微不那么正确。原因是 utf8mb4_unicode_ci 支持扩展映射,例如德语和其他语言中的 ß 等于 ssutf8mb4_unicode_ci 也支持收缩和可忽略字符。utf8mb4_general_ci 是一个遗留排序,不支持扩展映射、收缩或可忽略字符。它只能进行一对一的字符比较。

另外,以下等式在 utf8mb4_general_ciutf8mb4_unicode_ci 中都成立(对于比较或搜索的效果,请参阅 第 12.8.6 节,“collation 的效果示例”):

Ä = A
Ö = O
Ü = U

这两个 collation 之间的一个区别是,以下等式在 utf8mb4_general_ci 中成立:

ß = s

而以下等式在 utf8mb4_unicode_ci 中成立,该 collation 支持德语 DIN-1 排序(也称为字典顺序):

ß = ss

如果 utf8mb4_unicode_ci 的排序不适合某种语言,MySQL 将实现语言特定的 Unicode collation。例如,utf8mb4_unicode_ci 对德语字典顺序和法语工作得很好,因此不需要创建特殊的 utf8mb4 collation。

utf8mb4_general_ci 也适用于德语和法语,除了 ß 等于 s,而不是等于 ss。如果您的应用程序接受这种情况,您应该使用 utf8mb4_general_ci,因为它更快。如果这不可接受(例如,如果您需要德语字典顺序),请使用 utf8mb4_unicode_ci,因为它更准确。

如果您需要德语 DIN-2(电话簿)顺序,请使用 utf8mb4_german2_ci collation,该 collation 将以下字符集视为相等:

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

utf8mb4_german2_ci 类似于 latin1_german2_ci,但后者不将 Æ 视为等于 AEŒ 视为等于 OE。由于 utf8mb4_general_ci 足以满足德语字典顺序,因此没有对应的 utf8mb4_german_ci

字符排序权重

字符的排序权重是根据以下方式确定的:

  • 对于所有 Unicode collations 除了 _bin(二进制)collations,MySQL 都会执行表查找以找到字符的排序权重。

  • 对于 _bin collations 除了 utf8mb4_0900_bin,权重基于代码点,可能添加了前导零字节。

  • 对于 utf8mb4_0900_bin,权重是 utf8mb4 编码字节。排序顺序与 utf8mb4_bin 相同,但速度更快。

可以使用 WEIGHT_STRING() 函数显示比较权重。(见 第 14.8 节,“字符串函数和操作符”。)如果排序规则使用权重查找表,但字符不在表中(例如,因为它是一个 字符),那么比较权重的确定将变得更加复杂:

  • 对于 BMP 字符在通用排序规则中 (xxx_general_ci),权重是代码点。

  • 对于 BMP 字符在 UCA 排序规则中(例如,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;

    结果是一个由两个比较元素组成的序列,aaaa 后跟 bbbb。例如:

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

    因此,U+04cf CYRILLIC SMALL LETTER PALOCHKA (ӏ) 在所有 UCA 4.0.0 排序规则中大于 U+04c0 CYRILLIC LETTER PALOCHKA (Ӏ)。在 UCA 5.2.0 排序规则中,所有帕洛奇卡排序在一起。

  • 对于补充字符在通用排序规则中,权重是 0xfffd REPLACEMENT CHARACTER 的权重。对于补充字符在 UCA 4.0.0 排序规则中,它们的比较权重是 0xfffd。也就是说,对于 MySQL,所有补充字符彼此相等,且大于几乎所有 BMP 字符。

    使用 Deseret 字符和 COUNT(DISTINCT) 的示例:

    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。)

    使用楔形文字字符和 WEIGHT_STRING() 的示例:

    /*
    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 的权重。

    所有补充字符彼此相等的规则不是最优的,但不太可能引起问题。这些字符非常罕见,因此很少有多字符字符串完全由补充字符组成。在日本,因为补充字符是罕见的汉字 ideographs,典型用户并不关心它们的顺序。 如果您真的想按 MySQL 规则和第二arily 按代码点值排序,它很容易:

    ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
  • 基于UCA版本高于4.0.0的补充字符(例如:xxx_unicode_520_ci),补充字符不一定都具有相同的排序权重。一些具有来自UCA allkeys.txt文件的明确权重。其他的权重是根据这个算法计算的:

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

有一个区别是“按字符的代码值排序和“按字符的二进制表示排序,”这个区别只出现在 utf16_bin中,因为surrogates的存在。

假设 utf16_binutf16的二进制排序)是一个字节-by-byte的比较,而不是“字符-by-character.如果是这样,那么 utf16_bin中的字符顺序将不同于 utf8mb4_bin中的顺序。例如,下面的表格显示了两个罕见的字符。第一个字符在 E000-FFFF范围内,因此它大于surrogate但小于补充字符。第二个字符是一个补充字符。

Code point  Character                    utf8mb4      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。他们也按 utf8mb4值排序,因为 0xef < 0xf0。但是,他们不按 utf16值排序,如果我们使用字节-by-byte比较,因为 0xff > 0xd8

所以 MySQL 的 utf16_bin 排序不是“字节-by-byte. 它是“按代码点. 当 MySQL 看到 utf16中的补充字符编码时,它将其转换为字符的代码点值,然后比较。因此,utf8mb4_binutf16_bin 排序相同。这与 SQL:2008 标准要求的 UCS_BASIC 排序一致:UCS_BASIC 是一个排序,其中排序完全由字符串中字符的 Unicode 标量值确定。它适用于 UCS 字符repertoire。由于每个字符repertoire都是 UCS 字符repertoire 的子集,因此 UCS_BASIC 排序可能适用于每个字符集。注意 11:字符的 Unicode 标量值是其代码点视为无符号整数。

如果字符集是 ucs2,比较是字节-by-byte的,但是 ucs2 字符串不应该包含surrogates,反正。

杂项信息

The xxx_general_mysql500_ci 排序保持了原始 xxx_general_ci 排序的 pre-5.1.24 顺序,并允许对在 MySQL 5.1.24 之前创建的表进行升级(Bug #27877)。