MySQL 字符集:支持的字符集和排序规则
关于
要列出可用的字符集及其默认排序规则,请使用“SHOW CHARACTER SET”或查询“INFORMATION_SCHEMA”中的“CHARACTER_SETS”表。
MySQL支持的字符集:
- 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 编码,每个字符使用四个字节。
- utf8mb4,utf16,utf16le和utf32支持 BMP 之外的基本多语言平面(BMP)字符和补充字符。 utf8和ucs2仅支持 BMP 字符。
大多数 Unicode 字符集具有:
- 常规排序规则(名称中用“_general”表示或没有语言说明符),
- 二进制排序规则(名称中用“_bin”表示)
- 以及几种特定于语言的排序规则(由语言说明符表示)。
- utf16le 的排序规则支持是有限的。唯一可用的排序规则是 utf16le_general_ci 和 utf16le_bin 。这类似于 utf16_general_ci 和 utf16_bin。
例如,对于 utf8mb4:utf8mb4_general_ci 和 utf8mb4_bin 是其常规归类和二进制归类,而 utf8mb4_danish_ci 是其特定于语言的归类之一。
Unicode 排序算法
MySQL 根据“UNICODE COLLATION ALGORITHM”所述的 Unicode 排序算法(UCA)实现“xxx_unicode_ci”排序规则。
- “xxx_unicode_ci”排序仅部分支持 Unicode 归类算法。不支持某些字符,并且不完全支持组合标记。这主要影响越南语,约鲁巴语和一些较小的语言,例如 Navajo。
- 在字符串比较中,组合字符被认为与用单个 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 版本时,这些函数才能转换仅在 Unicode 版本高于 4.0.0 中具有大写和小写版本的字符。
特定语言的排序规则
如果仅基于 Unicode 排序规则算法(UCA)的排序不适用于某种语言,则 MySQL 将实现特定于语言的 Unicode 排序规则。特定于语言的排序规则基于 UCA,并带有其他语言定制规则。
下表中显示的语言名称表示特定于语言的排序规则。 Unicode 字符集可以包括一种或多种这些语言的排序规则:
Language | Language Specifier |
---|---|
Classical Latin | roman |
Croatian | croatian |
Czech | czech |
Danish | danish |
Esperanto | esperanto |
Estonian | estonian |
German phone book order | german2 |
Hungarian | hungarian |
Icelandic | icelandic |
Latvian | latvian |
Lithuanian | lithuanian |
Persian | persian |
Polish | polish |
Romanian | romanian |
Sinhala | sinhala |
Slovak | slovak |
Slovenian | slovenian |
Modern Spanish | spanish |
Traditional Spanish | spanish2 |
Swedish | swedish |
Turkish | turkish |
Vietnamese | vietnamese |
_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”是不支持扩展,收缩或可忽略字符的传统排序规则,它只能在字符之间进行一对一比较。
如:
ß = s
对于utf8_general_ci是正确的
ß = ss
对于utf8_unicode_ci是正确的。
- 如果使用 utf8_unicode_ci 的排序不适用于某种语言,则 MySQL 将实现 utf8 语言特定的排序规则。例如,utf8_unicode_ci 适用于德语字典顺序和法语,因此无需创建特殊的 utf8 排序规则。
字符排序权重
字符的归类权重确定如下:
- 对于除“_bin”(二进制)排序规则外的所有 Unicode 归类,MySQL 执行 table 查找以查找字符的归类权重。
- 对于“_bin”排序规则,权重基于代码点,可能添加了前导零字节。
- 可以使用“WEIGHT_STRING()”函数显示整理权重。
如果排序规则使用权重查找 table,但是 table 中没有字符,则排序权重确定变得更加复杂:
- 对于一般排序规则(“xxx_general_ci”)中的 BMP 字符,权重是代码点。
- 对于 UCA 归类中的 BMP 字符(例如“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 | +----------------------------------------------------------+
- 对于一般排序规则中的补充字符,权重是“0xfffd REPLACEMENT CHARACTER的权重”。对于 UCA 4.0.0 排序规则中的补充字符,其归类权重为“0xfffd”。也就是说,对于 MySQL,所有补充字符都彼此相等,并且几乎大于所有 BMP 字符。
- 所有补充字符都相等的规则不是最佳的,但是不会引起麻烦。这些字符非常少见,因此由多字符组成的字符串完全由补充字符组成非常罕见。如果您确实希望按 MySQL 规则对行进行排序,然后再按码点值对行进行排序,则很简单:
ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
- 所有补充字符都相等的规则不是最佳的,但是不会引起麻烦。这些字符非常少见,因此由多字符组成的字符串完全由补充字符组成非常罕见。如果您确实希望按 MySQL 规则对行进行排序,然后再按码点值对行进行排序,则很简单:
- 对于基于高于 4.0.0 的 UCA 版本的补充字符,补充字符不一定都具有相同的整理重量(例如“xxx_unicode_520_ci”)。
其他信息
“xxx_general_mysql500_ci”排序规则保留原始“xxx_general_ci”排序规则在 5.1.24 之前的顺序,并允许对在 MySQL 5.1.24 之前创建的 table 进行升级(缺陷号 27877)。【???】
亚洲字符集
支持的亚洲字符集包括中文,日文,韩文和泰文:
- big5(Big5 繁体中文)排序规则:
- big5_bin
- big5_chinese_ci(默认)【按笔划数排序】
- cp932(Windows 日语为 SJIS)排序规则:
- cp932_bin
- cp932_japanese_ci(默认)
- eucjpms(用于 Windows 日语的 UJIS)排序规则:
- eucjpms_bin
- eucjpms_japanese_ci(默认)
- euckr(EUC-KR 韩文)排序规则:
- euckr_bin
- euckr_korean_ci(默认)
- gb2312(GB2312 简体中文)排序规则:
- gb2312_bin
- gb2312_chinese_ci(默认)
- gbk(GBK 简体中文)排序规则:
- gbk_bin
- gbk_chinese_ci(默认)
- gb18030(中国国家标准 GB18030)排序规则:
- gb18030_bin
- gb18030_chinese_ci(默认)
- gb18030_unicode_520_ci
- sjis(Shift-JIS 日文)排序规则:
- sjis_bin
- sjis_japanese_ci(默认)
- tis620(TIS620 Thai)排序规则:
- tis620_bin
- tis620_thai_ci(默认)
- ujis(EUC-JP 日文)排序规则:
- ujis_bin
- ujis_japanese_ci(默认)
cp932 字符集
(日语,略)
gb18030 字符集
在 MySQL 中,gb18030字符集对应于“中华人民共和国国家标准 GB 18030-2005:信息技术中文编码字符集”,它是中华人民共和国(PRC)的官方字符集。
MySQL gb18030 字符集的特征:
- 支持 GB 18030-2005 标准定义的所有代码点。 (GB 8431A439,GB 90308130)和(GB E3329A36,GB EF39EF39)范围内未分配的代码点被视为'?'(0x3F)。未分配代码点的转换返回“ ?”。
- 支持所有 GB18030 代码点的上,下转换。还支持 Unicode 定义的大小写折叠(基于CaseFolding-6.3.0.txt)。
- 支持与其他字符集之间的数据转换。
- 支持 SQL 语句,例如“SET NAMES”。
- 支持gb18030字符串之间,gb18030字符串与其他字符集的字符串之间的比较。如果字符串具有不同的字符集,则会进行转换。还支持包含或忽略尾随空格的比较。
- Unicode 中的专用区域(U E000,U F8FF)Map 到gb18030。
- (U D800,U DFFF)和 GB18030 之间没有映射。尝试转换此范围内的代码点将返回“ ?”。
- 如果输入序列不合法,则会返回错误或警告。如果在CONVERT()中使用了非法序列,则返回错误。否则,将返回警告。
- 为了与utf8和utf8mb4保持一致,“UPPER”不支持连字。
- 使用gb18030_unicode_520_ci归类时,对连字的搜索还匹配大写连字。
- 如果一个字符有多个大写字符,则所选的大写字符为小写字符本身。
- 多字节的最小长度为 1,最大为 4.字符集使用前 1 个或 2 个字节来确定序列的长度。
支持的排序规则:
- gb18030_bin:二进制排序规则。
- gb18030_chinese_ci:默认排序规则,支持拼音。非中文字符的排序基于原始排序键的顺序。如果“UPPER(ch)”存在,则原始排序键为“GB(UPPER(ch))”。否则,原始排序键为“GB(ch)”。汉字根据 Unicode 通用语言环境数据存储库(CLDR 24)中定义的拼音排序规则进行排序。非汉字在汉字之前排序,但“GB+FE39FE39”除外,这是最大的代码点。
- gb18030_unicode_520_ci:Unicode 排序规则。如果需要确保连字正确排序,请使用此排序规则。【???】
二进制字符集
“binary”字符集是二进制字符串的字符集,二进制字符串是字节序列。 “binary”字符集具有一个排序规则,也称为“binary”。比较和排序基于数字字节值,而不是基于数字字符代码值(对于多字节字符,数字字符代码值不同于数字字节值【???】)。
对于binary字符集,不区分大小写和重音符号的概念:
- 对于存储为二进制字符串的单字节字符,字符和字节边界是相同的,因此在比较中字母和重音差异很明显。也就是说,binary 排序规则区分大小写和区分重音。
mysql> SET NAMES 'binary'; mysql> SELECT CHARSET('abc'), COLLATION('abc'); +----------------+------------------+ | CHARSET('abc') | COLLATION('abc') | +----------------+------------------+ | binary | binary | +----------------+------------------+ mysql> SELECT 'abc' = 'ABC', 'a' = 'ä'; +---------------+------------+ | 'abc' = 'ABC' | 'a' = 'ä' | +---------------+------------+ | 0 | 0 | +---------------+------------+
- 对于存储为二进制字符串的多字节字符,字符和字节边界不同。字符边界丢失,因此依赖于它们的比较没有意义。
- 要执行二进制字符串的字母大小写转换,请首先使用适合于存储在字符串中的数据的字符集将其转换为非二进制字符串:
mysql> SET @str = BINARY 'New York'; mysql> SELECT LOWER(@str), LOWER(CONVERT(@str USING utf8mb4)); +-------------+------------------------------------+ | LOWER(@str) | LOWER(CONVERT(@str USING utf8mb4)) | +-------------+------------------------------------+ | New York | new york | +-------------+------------------------------------+
- 要执行二进制字符串的字母大小写转换,请首先使用适合于存储在字符串中的数据的字符集将其转换为非二进制字符串:
- 要将字符串表达式转换为二进制字符串,这些结构是等效的:
BINARY expr CAST(expr AS BINARY) CONVERT(expr USING BINARY)
- 如果值是字符串常量,则可以使用“_binary”导引器将其指定为二进制字符串。例如:
_binary 'a'
- 十六进制字符和位值字符也可以使用“_binary”引入程序,但这不是必需的;这样的字符默认情况下是二进制字符串。【???】