本节介绍可用于 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 编码,每个字符使用四个字节。
utf8mb4
、utf16
、
utf16le
和utf32
支持基本多语言平面 (BMP) 字符和位于 BMP 之外的增补字符。utf8
并且
ucs2
只支持 BMP 字符。
大多数 Unicode 字符集都有一个通用排序规则(_general
在名称中用 表示或没有语言说明符)、二进制排序规则(
_bin
在名称中用 表示)和几种特定于语言的排序规则(由语言说明符表示)。例如,forutf8mb4
和
utf8mb4_general_ci
是
utf8mb4_bin
它的一般排序规则和二进制排序规则,并且utf8mb4_danish_ci
是它特定于语言的排序规则之一。
的归类支持utf16le
是有限的。唯一可用的归类是
utf16le_general_ci
and
utf16le_bin
。这些类似于
utf16_general_ci
和
utf16_bin
。
MySQL
根据
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 字符编写的相同字符,并且这两个字符被认为具有不同的长度(例如,由
xxx
_unicode_ciCHAR_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 |
克罗地亚语排序规则是为这些克罗地亚语字母量身定制的:
Č
, Ć
,
Dž
, Đ
,
Lj
, Nj
,
Š
, Ž
。
丹麦语归类也可用于挪威语。
对于古典拉丁排序规则,I
and
J
比较相等,
U
andV
比较相等。
西班牙语排序规则可用于现代和传统西班牙语。对于两者, (n-tilde) 是和
ñ
之间的单独字母。此外,对于传统的西班牙语,
是和之间的单独字母
,并且
是和之间的单独字母
。
n
o
ch
c
d
ll
l
m
传统的西班牙语排序规则也可用于阿斯图里亚斯语和加利西亚语。
瑞典归类包括瑞典规则。例如,在瑞典语中,存在以下关系,这不是说德语或法语的人所期望的:
Ü = Y < Ö
对于任何 Unicode 字符集,使用排序规则执行的操作
比使用排序规则的操作更快
xxx
_general_ci
。例如,
xxx
_unicode_ciutf8_general_ci
排序规则的比较比
utf8_unicode_ci
. 原因是
utf8_unicode_ci
支持扩展等映射;也就是说,当一个字符与其他字符的组合比较时。例如,
在德语和其他一些语言
ß
中等于。还支持缩写和可忽略的字符。ss
utf8_unicode_ci
utf8_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 节,“字符串函数和运算符”。)如果排序规则使用权重查找表,但字符不在表中(例如,因为它是“新”字符),则排序权重确定变得更加复杂:
对于通用排序规则 (
) 中的 BMP 字符,权重是代码点。xxx
_general_ci对于 UCA 归类(例如,
特定于语言的归类)中的 BMP 字符,应用以下算法:xxx
_unicode_ciif (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_ci0x0dc6
,而 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
并且0E4A
是 UCA 4.0.0中的主要权重。FFFD
是 KAB 和 KISH 的权重。所有增补字符彼此相等的规则不是最优的,但预计不会造成麻烦。这些字符非常罕见,因此多字符字符串完全由增补字符组成的情况非常罕见。在日本,由于补充字符是晦涩的汉字表意文字,所以一般用户无论如何都不关心它们的顺序。如果您真的希望行按 MySQL 规则排序,然后按代码点值排序,很容易:
ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
对于基于高于 4.0.0 的 UCA 版本的增补字符(例如,
),增补字符不一定都具有相同的整理权重。有些具有来自 UCAxxx
_unicode_520_ciallkeys.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
。它们按
utf8
值排序,因为0xef
< 0xf0
。utf16
但是如果我们使用逐字节比较,它们不是按值排序的
,因为0xff
>
0xd8
。
所以MySQL的utf16_bin
排序不是
“逐字节的”。”它是“按代码点。”当 MySQL 在 中看到增补字符编码时utf16
,它会转换为字符的代码点值,然后进行比较。因此,
utf8_bin
和utf16_bin
是相同的排序。这与 UCS_BASIC 归类的 SQL:2008 标准要求一致:
“UCS_BASIC 是一种排序规则,其中排序完全由要排序的字符串中字符的 Unicode 标量值决定。它适用于 UCS 字符库。由于每个字符指令集都是 UCS 指令集的一个子集,因此 UCS_BASIC 归类可能适用于每个字符集。注 11:字符的 Unicode 标量值是将其代码点视为无符号整数。”
如果字符集是ucs2
,则比较是逐字节进行的,但ucs2
无论如何,字符串不应包含代理项。