Documentation Home

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 编码,每个字符使用两个字节。

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

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

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

utf8mb4utf16utf16leutf32支持基本多语言平面 (BMP) 字符和位于 BMP 之外的增补字符。utf8并且 ucs2只支持 BMP 字符。

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

的归类支持utf16le是有限的。唯一可用的归类是 utf16le_general_ciand utf16le_bin。这些类似于 utf16_general_ciutf16_bin

Unicode 归类算法 (UCA) 版本

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

基于高于 4.0.0 的 UCA 版本的 Unicode 归类包括归类名称中的版本。因此, utf8_unicode_520_ci基于 UCA 5.2.0 权重密钥 ( http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt )。

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

特定于语言的排序规则

如果仅基于 Unicode 归类算法 (UCA) 的排序不适用于某种语言,则 MySQL 会实现特定于语言的 Unicode 归类。特定于语言的归类是基于 UCA 的,具有额外的语言定制规则。此类规则的示例将在本节后面出现。对于有关特定语言顺序的问题, unicode.org在http://www.unicode.org/cldr/charts/30/collat ​​ion/index.html提供了通用语言环境数据存储库 (CLDR) 整理图表 。

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

表 10.3 Unicode 归类语言说明符

语言说明符
古典拉丁语 roman
克罗地亚语 croatian
捷克语 czech
丹麦语 danish
世界语 esperanto
爱沙尼亚语 estonian
德国电话簿订单 german2
匈牙利 hungarian
冰岛的 icelandic
拉脱维亚语 latvian
立陶宛语 lithuanian
波斯语 persian
抛光 polish
罗马尼亚语 romanian
僧伽罗语 sinhala
斯洛伐克语 slovak
斯洛文尼亚语 slovenian
现代西班牙语 spanish
传统的西班牙语 spanish2
瑞典 swedish
土耳其 turkish
越南语 vietnamese

克罗地亚语排序规则是为这些克罗地亚语字母量身定制的: Č, Ć, , Đ, Lj, Nj, Š, Ž

丹麦语归类也可用于挪威语。

对于古典拉丁排序规则,Iand J比较相等, UandV比较相等。

西班牙语排序规则可用于现代和传统西班牙语。对于两者, (n-tilde) 是和 ñ之间的单独字母。此外,对于传统的西班牙语, 是和之间的单独字母 ,并且 是和之间的单独字母 。 nochcdlllm

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

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

Ü = Y < Ö

_general_ci 与 _unicode_ci 归类

对于任何 Unicode 字符集,使用排序规则执行的操作 xxx_general_ci 比使用排序规则的操作更快 xxx_unicode_ci 。例如, utf8_general_ci排序规则的比较比 utf8_unicode_ci. 原因是 utf8_unicode_ci支持扩展等映射;也就是说,当一个字符与其他字符的组合比较时。例如, 在德语和其他一些语言 ß中等于。还支持缩写和可忽略的字符。ssutf8_unicode_ciutf8_general_ci 是不支持扩展、收缩或可忽略字符的旧式排序规则。它只能在字符之间进行一对一的比较。

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

Ä = A
Ö = O
Ü = U

排序规则之间的区别在于,这适用于 utf8_general_ci

ß = s

而对于utf8_unicode_ci支持德语 DIN-1 排序(也称为字典顺序)的 ,情况也是如此:

ß = ss

如果 ordering with不适用于某种语言,则 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排序规则,权重基于代码点,可能添加前导零字节。

可以使用该 WEIGHT_STRING()功能显示整理重量。(请参阅 第 12.8 节,“字符串函数和运算符”。)如果排序规则使用权重查找表,但字符不在表中(例如,因为它是字符),则排序权重确定变得更加复杂:

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

  • 对于 UCA 归类(例如, xxx_unicode_ci 特定于语言的归类)中的 BMP 字符,应用以下算法:

    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 归类, is 大于U+04c0 CYRILLIC LETTER PALOCHKA. 使用 UCA 5.2.0 归类,所有 palochkas 一起排序。

  • 对于一般排序规则中的增补字符,权重是 的权重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

    0E33并且0E4AUCA 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),增补字符不一定都具有相同的整理权重。有些具有来自 UCAallkeys.txt文件的明确权重。其他人根据此算法计算权重:

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

按字符的代码值排序”按字符的二进制表示排序 之间存在差异,这种差异仅在 , 中出现utf16_bin,因为有代理项。

假设utf16_bin(的二进制排序规则)是逐字节而不是 逐字符utf16”的二进制比较。如果是这样,字符的顺序将与 中的顺序不同。例如,下图显示了两个稀有字符。第一个字符在范围内 - ,因此它大于代理项但小于补充项。第二个字符是一个补充。 utf16_binutf8_binE000FFFF

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。它们按 utf8值排序,因为0xef < 0xf0utf16但是如果我们使用逐字节比较,它们不是按值排序的 ,因为0xff> 0xd8

所以MySQL的utf16_bin排序不是 逐字节的”。它是按代码点。当 MySQL 在 中看到增补字符编码时utf16,它会转换为字符的代码点值,然后进行比较。因此, utf8_binutf16_bin 是相同的排序。这与 UCS_BASIC 归类的 SQL:2008 标准要求一致: UCS_BASIC 是一种排序规则,其中排序完全由要排序的字符串中字符的 Unicode 标量值决定。它适用于 UCS 字符库。由于每个字符指令集都是 UCS 指令集的一个子集,因此 UCS_BASIC 归类可能适用于每个字符集。注 11:字符的 Unicode 标量值是将其代码点视为无符号整数。

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

杂项资料

xxx_general_mysql500_ci 归类保留原始归类的 pre-5.1.24 顺序, 并 xxx_general_ci 允许升级在 MySQL 5.1.24 之前创建的表(错误 #27877)。