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
。
utf8mb4
,utf16
,utf16le
,和utf32
支持基本多语种平面(BMP)字符和补充字符谎言BMP外部。utf8
并且ucs2
仅支持BMP字符。
大多数Unicode字符集具有常规校验规则(由_general
名称表示或没有语言说明符),二进制校验规则(由_bin
名称表示)以及几种特定于语言的校验规则(由语言说明符表示)。例如,对于utf8mb4
,utf8mb4_general_ci
和utf8mb4_bin
是一般性和二进制归类,并且utf8mb4_danish_ci
是它的特定语言归类之一。
大多数字符集具有单个二进制校验规则。utf8mb4
是有两个例外:utf8mb4_bin
和(从MySQL 8.0.17开始)utf8mb4_0900_bin
。这两个二进制校验规则具有相同的校验顺序,但是通过其pad属性和校验权重特征来区分。请参见归类填充属性和字符归类权重。
校验规则支持utf16le
是有限的。仅有的校验规则是utf16le_general_ci
和utf16le_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 PAD
与PAD SPACE
基于9.0.0之前的UCA版本的归类中使用的pad属性相比,它们的pad属性也为。为了比较非二进制字符串,NO PAD
校验规则将字符串末尾的空格与其他任何字符一样对待(请参阅“比较中的尾随空格处理”)。
要确定校验规则的pad属性,请使用INFORMATION_SCHEMA
COLLATIONS
具有一PAD_ATTRIBUTE
列的表。例如:
mysql>SELECT COLLATION_NAME, PAD_ATTRIBUTEFROM INFORMATION_SCHEMA.COLLATIONSWHERE 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 | +---------------------------- +--------------- +
具有校验规则的非二进制字符串值(CHAR
,VARCHAR
和TEXT
)的比较NO PAD
与其他校验规则在尾随空格方面有所不同。例如,将'a'
和'a '
比较为不同的字符串,而不是相同的字符串。使用的二进制校验规则可以看出这一点utf8mb4
。对于垫属性utf8mb4_bin
的PAD SPACE
,而对于utf8mb4_0900_bin
它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 t1VALUES ('a'); Query OK, 1 row affected (0.01 sec) mysql>SELECT *FROM t1WHERE c = 'a '; +------ + | c | +------ + | a | +------ + 1 row in set (0.00 sec) mysql>ALTER TABLE t1MODIFY c CHAR(10)COLLATE utf8mb4_0900_bin; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql>SELECT *FROM t1WHERE 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 |
克罗地亚归类是专为这些克罗地亚字母:Č
,Ć
,Dž
,Đ
,Lj
,Nj
,Š
,Ž
。
丹麦归类也可用于挪威语。
对于日语,utf8mb4
字符集包括utf8mb4_ja_0900_as_cs
和utf8mb4_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
。此外,对于传统的西班牙文,ch
是c
和之间的单独字母d
,并且ll
是l
和之间的单独字母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 0x04CFCOLLATE 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 utf32COLLATE utf32_unicode_ci);INSERT INTO tVALUES (0xfffd); /* REPLACEMENT CHARACTER */INSERT INTO tVALUES (0x010412); /* DESERET CAPITAL LETTER BEE */INSERT INTO tVALUES (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 utf32COLLATE utf32_unicode_ci);INSERT INTO tVALUES (0x000000410001218f000121a700000042);SELECT HEX(WEIGHT_STRING(s1))FROM t;结果是:
0E33 FFFD FFFD 0E4A
0E33
和0E4A
是UCA 4.0.0中的主要权重。FFFD
是KAB和KISH的重量。所有补充字符都相等的规则不是最佳的,但是不会引起麻烦。这些字符非常少见,因此由多字符组成的字符串完全由补充字符组成非常罕见。在日本,由于辅助字符是晦涩的汉字表意文字,因此一般用户根本不在乎它们的顺序。如果您确实希望按MySQL规则校验,然后按代码点值校验的行,则很简单:
ORDER BY s1COLLATE utf32_unicode_ci, s1COLLATE 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_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_bin
和utf16_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)。