• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • unicode字符集

    本节介绍可用于Unicode字符集的校验规则及其区分属性。有关Unicode的一般信息,请参见“ Unicode支持”。

    MySQL支持多种Unicode字符集:

    • utf8mb4:Unicode字符集的UTF-8编码,每个字符使用1-4个字节。
    • utf8mb3:Unicode字符集的UTF-8编码,每个字符使用一到三个字节。
    • utf8:的别名utf8mb3
    • ucs2:Unicode字符集的UCS-2编码,每个字符使用两个字节。
    • utf16:Unicode字符集的UTF-16编码,每个字符使用两个或四个字节。像,ucs2但扩展了辅助字符。
    • utf16le:Unicode字符集的UTF-16LE编码。就像utf16小端而不是大端。
    • utf32:Unicode字符集的UTF-32编码,每个字符使用四个字节。
    注意

    utf8mb3字符集已被弃用,并将在将来的MySQL版本中删除。请utf8mb4改用。尽管utf8目前是的别名utf8mb3,但在某些时候utf8会成为对utf8mb4。为避免对的含义含糊不清utf8,请考虑utf8mb4为字符集引用而不是显式指定utf8

    utf8mb4utf16utf16le,和utf32支持基本多语种平面(BMP)字符和补充字符谎言BMP外部。utf8并且ucs2仅支持BMP字符。

    大多数Unicode字符集具有常规校验规则(由_general名称表示或没有语言说明符),二进制校验规则(由_bin名称表示)以及几种特定于语言的校验规则(由语言说明符表示)。例如,对于utf8mb4utf8mb4_general_ciutf8mb4_bin是一般性和二进制归类,并且utf8mb4_danish_ci是它的特定语言归类之一。

    大多数字符集具有单个二进制校验规则。utf8mb4是有两个例外:utf8mb4_bin和(从MySQL 8.0.17开始)utf8mb4_0900_bin。这两个二进制校验规则具有相同的校验顺序,但是通过其pad属性和校验权重特征来区分。请参见归类填充属性和字符归类权重。

    校验规则支持utf16le是有限的。仅有的校验规则是utf16le_general_ciutf16le_bin。这些与utf16_general_ci和相似utf16_bin

    • Unicode校验算法(UCA)版本
    • 校验垫属性
    • 特定语言的归类
    • _general_ci与_unicode_ci归类
    • 字符校验权重
    • 杂项信息

    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()函数返回或在结果集元数据中)。

    基于UCA版本高于4.0.0的Unicode归类在归类名称中包含该版本。例子:

    • utf8mb4_unicode_520_ci基于UCA 5.2.0配重键(http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt),
    • utf8mb4_0900_ai_ci基于UCA 9.0.0重量键(http://www.unicode.org/Public/UCA/9.0.0/allkeys.txt)。

    LOWER()UPPER()根据它们的自变量的核对功能执行情况下折叠。仅当参数校验规则使用足够高的UCA版本时,这些函数才会转换仅在高于4.0.0的Unicode版本中具有大写和小写版本的字符。

    校验垫属性

    基于UCA 9.0.0及更高版本的归类比基于9.0.0之前的UCA版本的归类要快。NO PADPAD SPACE基于9.0.0之前的UCA版本的归类中使用的pad属性相比,它们的pad属性也为。为了比较非二进制字符串,NO PAD校验规则将字符串末尾的空格与其他任何字符一样对待(请参阅“比较中的尾随空格处理”)。

    要确定校验规则的pad属性,请使用INFORMATION_SCHEMACOLLATIONS具有一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_binPAD SPACE,而对于utf8mb4_0900_binNO 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)
    

    特定语言的归类

    如果仅基于Unicode校验规则算法(UCA)的校验不适用于某种语言,则MySQL将实现特定于语言的Unicode校验规则。特定于语言的归类基于UCA,并带有其他语言定制规则。此类规则的示例将在本节后面介绍。对于有关特定语言顺序的问题, unicode.org在http://www.unicode.org/cldr/charts/30/collation/index.html上提供了公共区域数据存储库(CLDR)归类图。

    例如,非特定于utf8mb4_0900_ai_ci语言和特定于语言的 Unicode归类分别具有以下特征:utf8mb4_LOCALE_0900_ai_ci

    • 校验规则基于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
    古典拉丁la要么roman
    克罗地亚语hr要么croatian
    捷克文cs要么czech
    丹麦文da要么danish
    世界语eo要么esperanto
    爱沙尼亚语et要么estonian
    德国电话簿订单de_pb要么german2
    匈牙利hu要么hungarian
    冰岛的is要么icelandic
    日本ja
    拉脱维亚语lv要么latvian
    立陶宛语lt要么lithuanian
    波斯语persian
    抛光pl要么polish
    罗马尼亚语ro要么romanian
    俄语ru
    僧伽罗语sinhala
    斯洛伐克文sk要么slovak
    斯洛文尼亚文sl要么slovenian
    现代西班牙语es要么spanish
    传统西班牙语es_trad要么spanish2
    瑞典sv要么swedish
    土耳其tr要么turkish
    越南文vi要么vietnamese

    克罗地亚归类是专为这些克罗地亚字母:ČĆĐLjNjŠŽ

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

    对于日语,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使用四个。

    For Classical Latin collations that are accent-insensitive,I and J compare as equal, and U and V compare as equal.I and J, and U and V compare as equal on the base letter level. In other words,J is regarded as an accented I, and U is regarded as an accented V.

    西班牙语归类可用于现代和传统西班牙语。对于两者,ñ(n-tilde)是n和之间的单独字母o。此外,对于传统的西班牙文,chc和之间的单独字母d,并且lll和之间的单独字母m

    传统的西班牙归类也可以用于阿斯图里亚斯语和加利西亚语。

    瑞典归类包括瑞典规则。例如,在瑞典语中,以下关系成立,这不是德语或法语使用者所期望的:

    Ü = Y < Ö
    

    _general_ci与_unicode_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_ci和中都具有以下相等性utf8_unicode_ci(有关比较或搜索中的影响,请参见“字符集和校验规则分配的示例”):

    Ä = A
    Ö = O
    Ü = U
    

    归类之间的不同之处在于utf8_general_ci

    ß = s
    

    而对于而言utf8_unicode_ci,这是正确的,它支持德语DIN-1校验(也称为字典顺序):

    ß = ss
    

    utf8如果校验utf8_unicode_ci不适用于某种语言,则 MySQL将实现特定于语言的校验规则。例如,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

    字符校验权重

    角色的归类权重确定如下:

    • 对于除_bin(二进制)归类外的所有Unicode归类,MySQL执行表查找以查找字符的归类权重。
    • 对于_bin除以外的归类utf8mb4_0900_bin,权重基于代码点,可能添加了前导零字节。
    • 对于utf8mb4_0900_bin,权重是utf8mb4编码字节。校验顺序与相同utf8mb4_bin,但速度更快。

    可以使用该WEIGHT_STRING()功能显示校验权重。(请参见“字符串函数和运算符”。)如果校验规则使用权重查找表,但表中没有字符(例如,因为它是“ new ”字符),则校验权重确定变得更加复杂:

    • 对于一般归类(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归类而言,都大于U +04c0 CYRILLIC LETTER PALOCHKA。使用UCA 5.2.0归类,所有palochka都可以校验。

    • 对于一般归类中的补充字符,权重是的权重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的重量。

      所有补充字符都相等的规则不是最佳的,但是不会引起麻烦。这些字符非常少见,因此由多字符组成的字符串完全由补充字符组成非常罕见。在日本,由于辅助字符是晦涩的汉字表意文字,因此一般用户根本不在乎它们的顺序。如果您确实希望按MySQL规则校验,然后按代码点值校验的行,则很简单:

      ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
      
    • 对于基于高于4.0.0的UCA版本的补充字符(例如xxx_unicode_520_ci),补充字符不一定都具有相同的校验权重。有些具有来自UCA allkeys.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
    

    The two characters in the chart are in order by code point value because 0xff9d<0x10384. And they are in order by utf8 value because 0xef<0xf0. But they are not in order by utf16 value, if we use byte-by-byte comparison, because 0xff>0xd8.

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

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

    杂项信息

    这些xxx_general_mysql500_ci归类保留了原始xxx_general_ci归类在5.1.24之前的顺序,并允许对在MySQL 5.1.24之前创建的表进行升级(缺陷号27877)。