A.11 MySQL 5.7 FAQ:MySQL 中文,日文和韩 Literals 符集

这套常见问题来自 MySQL 的支持和开发小组在处理许多有关 CJK(中日韩)问题的经验。


**A.11.1. **
MySQL 中提供哪些 CJK 字符集?
CJK 字符集的列 table 可能会因您的 MySQL 版本而异。例如,MySQL 5.7.4 之前不支持gb18030字符集。但是,由于适用语言的名称出现在INFORMATION_SCHEMA.CHARACTER_SETStable 中每个条目的DESCRIPTION列中,因此您可以使用此查询获取所有非 Unicode CJK 字符集的当前列 table:
mysql> SELECT CHARACTER_SET_NAME,说明
FROM INFORMATION_SCHEMA.CHARACTER_SETS
像'%Chin%'这样的描述
或说明,例如“%Japanese%”
或说明,例如'%Korean%'
ORDER BY CHARACTER_SET_NAME;
+--------------------+---------------------------------+
CHARACTER_SET_NAME描述
+--------------------+---------------------------------+
big5Big5 繁体中文
cp932Windows 日语的 SJIS
eucjpmsWindows 日语版 UJIS
euckrEUC-KR 韩文
gb18030中国国家标准 GB18030
gb2312GB2312 简体中文
gbkGBK 简体中文
sjisShift-JIS 日语
吉斯EUC-JP 日语
+--------------------+---------------------------------+
(有关更多信息,请参见第 24.2 节“ INFORMATION_SCHEMA CHARACTER_SETStable”。)
MySQL 支持 GB 的三种变体(* Guojia Biaozhun National Standard Simplified Chinese *)字符集,这些字符集在中华人民共和国中是官方的:gb2312gbk和(自 MySQL 5.7.4 起) gb18030
有时人们尝试将gbk个字符插入gb2312,并且大多数时候都可以使用,因为gbkgb2312的超集。但是最终他们尝试插入一个稀有的汉字,但它不起作用。 (有关示例,请参见 Bug#16072)。
在这里,我们尝试参考官方文档来明确说明gb2312gbk中哪些字符是合法的。在报告gb2312gbk错误之前,请检查以下参考:
MySQL gbk字符集实际上是“ Microsoft 代码页 936”。这与字符A1A4(中间点),A1AA(破折号),A6E0-A6F5A8BB-A8C0的官方gbk不同。
有关gbk/UnicodeMap 的列 table,请参见http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT
也可以将 CJK 字符存储在 Unicode 字符集中,尽管可用的排序规则可能无法完全按照您的期望对字符进行排序:
utf8ucs2字符集支持 Unicode 基本多语言平面(BMP)中的字符。这些字符的代码点值介于U+0000U+FFFF之间。
utf8mb4utf16utf16leutf32字符集支持 BMP 字符以及 BMP 之外的补充字符。补充字符的代码点值介于U+10000U+10FFFF之间。
用于 Unicode 字符集的归类确定对字符集中的字符进行排序(即区分)的能力:
基于 Unicode 归类算法(UCA)4.0.0 的归类仅区分 BMP 字符。
基于 UCA 5.2.0 或 9.0.0 的归类区分 BMP 和补充字符。
非 UCA 归类可能无法区分所有 Unicode 字符。例如,utf8mb4默认排序规则为utf8mb4_general_ci,它仅区分 BMP 字符。
此外,区分字符与根据给定 CJK 语言的约定对字符进行排序是不同的。当前,MySQL 只有一个特定于 CJK 的 UCA 归类gb18030_unicode_520_ci(需要使用非 Unicode gb18030字符集)。
有关 Unicode 归类及其区分属性(包括补充字符的归类属性)的信息,请参见第 10.10.1 节“ Unicode 字符集”

**A.11.2. **
我已在 table 格中插入 CJK 字符。 SELECT为什么将它们显示为“?”字符?
此问题通常是由于 MySQL 中的设置与应用程序或 os 的设置不匹配。以下是纠正这些类型问题的一些常用步骤:
请确定您使用的是哪个 MySQL 版本
使用语句SELECT VERSION();确定这一点。
确保数据库实际上正在使用所需的字符集
人们经常认为 Client 端字符集总是与服务器字符集或用于显示目的的字符集相同。但是,这两个都是错误的假设。您可以通过检查SHOW CREATE TABLE tablename的结果来确定,或者最好使用以下语句来确保:
SELECT 字符集名称,排序规则名称
FROM information_schema.columns
在哪里 table_schema = your_database_name
AND table_name = your_table_name
AND column_name = your_column_name;
确定未正确显示的一个或多个字符的十六进制值
您可以使用以下查询在 table* table_name 中获取列 column_name *的此信息:
SELECT HEX(column_name)
FROM table_name;
3F?字符的编码;这意味着?是实际存储在该列中的字符。发生这种情况最常见的原因是将特定字符从 Client 字符集转换为目标字符集时遇到了问题。
确保往返是可能的。当选择 literal (或 _introducer hexadecimal-value )时,是否得到 literal *
例如,日语片假名字符
Pe *(ペ')存在于所有 CJK 字符集中,并且具有代码点值(十六进制编码)0x30da。要测试此字符的往返行程,请使用以下查询:
SELECT 'ペ' AS `ペ`; /* or SELECT _ucs2 0x30da; */
如果结果也不是,则往返失败。
有关此类故障的错误报告,我们可能会要求您跟进SELECT HEX('ペ');。然后我们可以确定 Client 端编码是否正确。
*确保问题出在浏览器或其他应用程序上,而不是 MySQL *上。
使用mysqlClient 端程序来完成此任务。如果mysql正确显示字符,但您的应用程序未正确显示,则可能是由于系统设置引起的。
要确定您的设置,请使用SHOW VARIABLES语句,其输出应类似于此处显示的内容:
mysql>显示变量,例如'char%';
+--------------------------+----------------------------------------+
变量名价值
+--------------------------+----------------------------------------+
character_set_clientutf8
character_set_connectionutf8
character_set_databaselatin1
character_set_filesystem二进制
character_set_resultsutf8
character_set_serverlatin1
character_set_systemutf8
character_sets_dir/usr/local/mysql/share/mysql/charsets /
+--------------------------+----------------------------------------+
这些是连接到西部服务器(latin1是西欧字符集)的面向国际 Client(请注意使用utf8 Unicode)的典型字符集设置。
尽管 Unicode(在 Unix 上通常为utf8变体,在 Windows 上为ucs2变体)比拉丁文更可取,但通常不是您的 osUtil 所能提供的最佳支持。许多 Windows 用户发现 Microsoft 字符集(例如日语 Windows 的cp932)是合适的。
如果您无法控制服务器设置,并且不知道基础计算机将使用什么设置,请尝试更改您所在国家/locale 的通用字符集(euckr =韩国; gb18030gb2312gbk =中华人民共和国) ; big5 =台湾; sjisujiscp932eucjpms =日本; ucs2utf8 =任何地方)。通常,仅需要更改 Client 端以及连接和结果设置。 SET NAMES。语句一次更改所有三个。例如:
SET NAMES 'big5';
设置正确后,您可以通过编辑my.cnfmy.ini使其永久不变。例如,您可以添加如下所示的行:
[mysqld]
character-set-server=big5
[client]
default-character-set=big5
您的应用程序中使用的 API 配置设置也可能存在问题;请参阅*为什么我的 GUI 前端或浏览器不能正确显示 CJK 字符...?*了解更多信息。

**A.11.3. **
使用 Big5 中 Literals 符集时应该注意什么问题?
MySQL 支持在香港和台湾(中华民国)常见的 Big5 字符集。实际上,MySQL big5字符集是 Microsoft 代码页 950,它与原始big5字符集非常相似。
提出了添加HKSCS个 extensions 的功能请求。需要此扩展程序的人可能会发现感兴趣的 Bug#13577 的建议补丁。

**A.11.4. **
为什么日语字符集转换失败?
MySQL 支持sjisujiscp932eucjpms字符集以及 Unicode。通常需要在字符集之间进行转换。例如,可能有 Unix 服务器(通常使用sjisujis)和 WindowsClient 端(通常使用cp932)。
在下面的转换 table 中,ucs2列 table 示源,而sjiscp932ujiseucjpms列 table 示目标;也就是说,当我们使用CONVERT(ucs2)或将包含该值的ucs2列分配给sjiscp932ujiseucjpms列时,最后 4 列提供十六进制结果。
角色名称ucs2sjiscp932吉斯eucjpms
残破的酒吧00A63F3F8FA2C33F
全破断酒吧FFE43FFA553F8FA2
日元符号00A53F3F203F
全日元符号FFE5818F818FA1EF3F
瓷砖 007E7E7E7E7E
概述203E3F3F203F
水平杆2015815C815CA1BDA1BD
EM DASH20143F3F3F3F
反向实心005C815F5C5C5C
全宽“”FF3C3F815F3FA1C0
波浪破折号301C81603FA1C13F
全幅潮汐FF5E3F81603FA1C1
垂直线201681613FA1C23F
Parallel22253F81613FA1C2
减号2212817C3FA1DD3F
完整的连字符减号FF0D3F817C3FA1DD
CENT SIGN00A281913FA1F13F
百分号FFE03F81913FA1F1
指示牌00A381923FA1F23F
全磅指示牌FFE13F81923FA1F2
没有签名00AC81CA3FA2CC3F
完全不签名FFE23F81CA3FA2CC
现在考虑 table 的以下部分。
ucs2sjiscp932
没有签名00AC81CA3F
完全不签名FFE23F81CA
这意味着 MySQL 将NOT SIGN(Unicode U+00AC)转换为sjis代码点0x81CAcp932代码点3F。 (3F是问号(“?”.这是无法执行转换时始终使用的符号.)

**A.11.5. **
如果我想将 SJIS 81CA转换为cp932怎么办?
我们的答案是:“?”。这样做有弊端,许多人希望“松散”转换,以便sjis中的81CA (NOT SIGN)变成cp932中的81CA (FULLWIDTH NOT SIGN)

**A.11.6. **
MySQL 如何 table 示日元(¥)符号?
出现问题是因为某些日语字符集(sjiseuc都)将5C视为反向固线(\,也称为反斜杠),而其他版本则将其视为日元符号(¥)。
MySQL 仅遵循 JIS(日本工业标准)标准描述的一种版本。在 MySQL 中,* 5C总是反向固线(\)*。

**A.11.7. **
在 MySQL 中使用韩 Literals 符集时应该注意哪些问题?
从理论上讲,虽然euckr(扩展的 Unix 代码韩国语)字符集有多个版本,但仅注意到了一个问题。我们使用 EUC-KR 的“ ASCII”变体,其中代码点0x5c是 REVERSE SOLIDUS,即\,而不是 EUC-KR 的“ KS-Roman”变体,其中代码点0x5cWON SIGN()。这意味着您不能将 Unicode U+20A9转换为euckr
mysql> SELECT
以 euckr 的形式转换('₩'使用 euckr),
HEX(CONVERT('₩'using euckr))AS hexeuckr;
+-------+----------+
euckrhexeuckr
+-------+----------+
3F
+-------+----------+

**A.11.8. **
为什么会收到不正确的字符串值错误消息?
要解决此问题,请创建一个带有一个 Unicode(ucs2)列和一个中文(gb2312)列的 table。
mysql>创建 tablech
(ucs2 CHAR(3)字符集 ucs2,
gb2312 CHAR(3)CHARACTER SET gb2312);
在非严格 SQL 模式下,尝试将稀有字符放在两列中。
mysql> SET sql_mode ='';
mysql>插入 ch 值('A 汌 B','A 汌 B');
查询正常,1 行受影响,1 警告(0.00 秒)
INSERT发出警告。使用以下语句查看它是什么:
mysql>显示警告\ G
**** **** **** **** **** **** *** 1.行** **** **** **** **** **** **** *
Level: Warning
Code: 1366
消息:不正确的字符串值:第 1 行的列'gb2312'的' xE6xB1x8CB'
因此,这仅是关于gb2312列的警告。
mysql>从 ch 中选择 ucs2,HEX(ucs2),gb2312,HEX(gb2312);
+-------+--------------+--------+-------------+
ucs2十六进制(ucs2)gb2312十六进制(gb2312)
+-------+--------------+--------+-------------+
A 汌 B00416C4C0042A?B413F42
+-------+--------------+--------+-------------+
这里有几件事需要解释:
如前所述,字符不在gb2312字符集中。
如果您使用的是旧版本的 MySQL,则可能会看到不同的消息。
发生警告而非错误是因为 MySQL 未设置为使用严格的 SQL 模式。在非严格模式下,MySQL 会尽力做到最好,而不是放弃。在严格的 SQL 模式下,“不正确的字符串值”消息是作为错误而不是警告出现的,并且INSERT失败。

**A.11.9. **
为什么我的 GUI 前端或浏览器使用 Access,PHP 或其他 API 在我的应用程序中无法正确显示 CJK 字符?
使用mysqlClient 端获得与服务器的直接连接,然后在此处尝试相同的查询。如果mysql正确响应,则可能是您的应用程序界面需要初始化。使用mysql来告诉您SHOW VARIABLES LIKE 'char%';语句使用什么字符集或字符集。如果使用 Access,则很可能与连接器/ ODBC 连接。在这种情况下,应检查Configuring Connector/ODBC。例如,如果使用big5,则应 ImportingSET NAMES 'big5'。 (在这种情况下,不需要;字符.)如果使用的是 ASP,则可能需要在代码中添加SET NAMES。这是过去有效的示例:
<%
Session.CodePage=0
Dim strConnection
Dim Conn
strConnection="driver={MySQL ODBC 3.51 Driver};server=server;uid=username;"
&“ pwd =密码;数据库=数据库; stmt =设置名称'big5';”
设置 Conn = Server.CreateObject(“ ADODB.Connection”)
Conn.Open strConnection
%>
以几乎相同的方式,如果您在 Connector/NET 上使用latin1以外的任何字符集,则必须在连接字符串中指定该字符集。有关更多信息,请参见Connector/NET Connections
如果您使用的是 PHP,请尝试以下操作:

在这种情况下,我们使用SET NAMES更改了character_set_clientcharacter_set_connectioncharacter_set_results
PHP 应用程序中经常遇到的另一个问题与浏览器的假设有关。有时添加或更改<meta>标签足以解决此问题:例如,要确保用户代理将页面内容解释为UTF-8,请将<meta http-equiv="Content-Type" content="text/html; charset=utf-8">包含在 HTML 页面的<head>部分中。
如果使用的是 Connector/J,请参阅使用字符集和 Unicode

**A.11.10. **
我已经升级到 MySQL 5.7. 如何在字符集方面恢复到 MySQL 4.0 中的行为?
在 MySQL 版本 4.0 中,服务器和 Client 端都有一个“全局”字符集,并且由服务器 Management 员决定使用哪个字符。从 MySQL 版本 4.1 开始,此更改。现在发生的是“握手”,如第 10.4 节“连接字符集和排序规则”中所述:

Note





Client 端连接时,它将向服务器发送其要使用的字符集的名称。服务器使用该名称来设置character_set_clientcharacter_set_resultscharacter_set_connection系统变量。实际上,服务器使用字符集名称执行SET NAMES操作。



这样的结果是,您无法通过以mysqld开头--character-set-server=utf8来控制 Client 端字符集。但是,某些亚洲 Client 更喜欢 MySQL 4.0 的行为。为了保留这种行为,我们添加了mysqld开关--character-set-client-handshake,可以使用--skip-character-set-client-handshake将其关闭。如果以--skip-character-set-client-handshake开头mysqld,则当 Client 端连接时,它将向服务器发送其要使用的字符集的名称。但是,服务器会忽略来自 Client 端的请求
举例来说,假设您喜欢的服务器字符集是latin1。进一步假设 Client 端使用utf8,因为这是 Client 端 os 支持的。以latin1作为默认字符集启动服务器:
mysqld --character-set-server=latin1
然后使用默认字符集utf8启动 Client 端:
mysql --default-character-set=utf8
通过查看SHOW VARIABLES的输出可以看到结果设置:
mysql>显示变量,例如'char%';
+--------------------------+----------------------------------------+
|变量名|价值|
+--------------------------+----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem |二进制|
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir |/usr/local/mysql/share/mysql/charsets /
+--------------------------+----------------------------------------+
现在停止 Client 端,并使用mysqladmin停止服务器。然后再次启动服务器,但是这次告诉它跳过握手,如下所示:
mysqld --character-set-server=utf8 --skip-character-set-client-handshake
再次使用utf8作为默认字符集启动 Client 端,然后显示结果设置:
mysql>显示变量,例如'char%';
+--------------------------+----------------------------------------+
|变量名|价值|
+--------------------------+----------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem |二进制|
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir |/usr/local/mysql/share/mysql/charsets /
+--------------------------+----------------------------------------+
通过比较与SHOW VARIABLES的不同结果可以看到,如果使用--skip-character-set-client-handshake选项,则服务器将忽略 Client 端的初始设置。
|
*A.11.11. ** |为什么某些带有 CJK 字符的LIKEFULLTEXT搜索失败?|
||对于LIKE搜索,二进制字符串列类型(例如BINARYBLOB)存在一个非常简单的问题:我们必须知道字符的结尾。对于多字节字符集,不同的字符可能具有不同的八位位组长度。例如,在utf8中,A需要一个字节,而需要三个字节,如下所示:
+-------------------------+---------------------------+
| OCTET_LENGTH(_utf8'A')| OCTET_LENGTH(_utf8'ペ')|
+-------------------------+---------------------------+
| 1 | 3 |
+-------------------------+---------------------------+
如果我们不知道字符串中的第一个字符在哪里结束,那么我们也不知道第二个字符在哪里开始,在这种情况下,即使是非常简单的搜索(例如LIKE '_A%')也会失败。解决方案是使用定义为具有适当的 CJK 字符集的非二进制字符串列类型。例如:mycol TEXT CHARACTER SET sjis。或者,在比较之前转换为 CJK 字符集。
这就是 MySQL 无法允许不存在字符编码的原因之一。如果不严格拒绝不良 Importing,则无法知道字符在哪里结束。
对于FULLTEXT搜索,我们必须知道单词的开始和结束位置。对于西方语言,这几乎没有问题,因为其中大多数(如果不是全部)都使用易于识别的单词边界:空格字符。但是,亚洲写作通常不是这种情况。我们可以使用任意的中间量度,例如假设所有汉字都代 table 单词,或者(对于日语)取决于语法结尾从片假名到平假名的变化。但是,唯一确定的解决方案需要一个全面的单词列 table,这意味着我们必须在服务器中为支持的每种亚洲语言提供一个词典。这根本不可行。
|
A.11.12. ** |如何知道字符 X 是否在所有字符集中都可用?|
||大多数简体中文和基本非半形日语假名字符都出现在所有 CJK 字符集中。以下存储过程接受UCS-2 Unicode 字符,将其转换为其他字符集,并以十六进制显示结果。
DELIMITER //
创建过程 p_convert(ucs2_char CHAR(1)CHARACTER SET ucs2)
BEGIN
创建 tabletj
(ucs2 CHAR(1)字符集 ucs2,
utf8 CHAR(1)字符集 utf8,
big5 CHAR(1)字符集 big5,
cp932 CHAR(1)字符集 cp932,
eucjpms CHAR(1)字符集 eucjpms,
euckr CHAR(1)字符集 euckr,
gb2312 CHAR(1)字符集 gb2312,
gbk CHAR(1)字符集 gbk,
sjis CHAR(1)字符集 sjis,
ujis CHAR(1)字符集 ujis);
插入 tj(ucs2)值(ucs2_char);
更新 tj SET utf8 = ucs2,
big5=ucs2,
cp932=ucs2,
eucjpms=ucs2,
euckr=ucs2,
gb2312=ucs2,
gbk=ucs2,
sjis=ucs2,
ujis=ucs2;
/ 如果存在转换问题,则 UPDATE 会生成警告。 * /
SELECT hex(ucs2)AS ucs2,
hex(utf8)AS utf8,
hex(big5)AS big5,
hex(cp932)AS cp932,
hex(eucjpms)AS eucjpms,
hex(euckr)作为 euckr,
hex(gb2312)AS gb2312,
十六进制(gbk)AS gbk,
hex(sjis)AS sjis,
hex(ujis)AS ujis
FROM tj;
删除 tabletj;
END//
DELIMITER ;
Importing 可以是任何单个ucs2字符,也可以是该字符的代码值(十六进制 table 示)。例如,从 Unicode 的ucs2编码和名称(http://www.unicode.org/Public/UNIDATA/UnicodeData.txt)列 table 中,我们知道片假名字符
Pe 出现在所有 CJK 字符集中,并且其代码值为X'30DA'。如果我们将此值用作p_convert()的参数,则结果如下所示:
mysql>调用 p_convert(X'30DA');
+------+--------+------+-------+---------+-------+--------+------+------+------+
| ucs2 | utf8 | big5 | cp932 | eucjpms | euckr | gb2312 | gbk | sjis |吉斯|
+------+--------+------+-------+---------+-------+--------+------+------+------+
| 30DA | E3839A | C772 | 8379 | A5DA | ABDA | A5DA | A5DA | 8379 | A5DA |
+------+--------+------+-------+---------+-------+--------+------+------+------+
由于列值都不是3F(即问号字符?),因此我们知道每次转换都有效。
|
A.11.13. ** |为什么 CJK 字符串在 Unicode 中排序不正确? (I)|
||> [!NOTE|label:Note]



对于 MySQL 8.0 之前的 MySQL 版本,可能会出现此处描述的 CJK 排序问题。从 MySQL 8.0 开始,可以使用utf8mb4字符集和utf8mb4_ja_0900_as_cs归类来解决它们。



有时,人们会发现utf8_unicode_ciucs2_unicode_ci搜索或ORDER BY排序的结果不是他们认为的本机期望。尽管我们从不排除可能存在错误的可能性,但过去我们发现许多人没有正确阅读 Unicode 排序算法的标准权重 table。 MySQL 使用在http://www.unicode.org/Public/UCA/下找到的 table:
UCA 4.0.0table:http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt
其中包括xxx_unicode_ci个排序规则名称中没有版本号的排序规则。
UCA 5.2.0table 格:http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt
这包括归类名称中带有_520_的归类。
UCA 9.0.0table:http://www.unicode.org/Public/UCA/9.0.0/allkeys.txt
这包括归类名称中带有_0900_的归类。
为了处理新的 UCA 版本,我们创建了新的归类。我们对更改现有排序规则的 Sequences 非常谨慎,因为这会影响索引,从而可能导致出现错误#16526 中报告的情况,如下所示:
mysql>创建 tabletj(s1 CHAR(1)CHARACTER SET utf8 COLLATE utf8_unicode_ci);
查询正常,受影响的 0 行(0.05 秒)
mysql>插入 tj 值('が'),('か');
查询正常,受影响的 2 行(0.00 秒)
记录:2 重复:0 警告:0
mysql> SELECT * FROM tj WHERE s1 ='か';
+------+
| s1 |
+------+
|が|
|か|
+------+
第一个结果行中的字符不是我们搜索的字符。 MySQL 为什么要检索它?首先,我们寻找 Unicode 代码点值,这可以通过读取ucs2版字符的十六进制数字来实现:
mysql> SELECT s1,从 tj 十六进制(CONVERT(s1 using ucs2));
+------+-----------------------------+
| s1 |十六进制(使用 ucs2 转换(s1))|
+------+-----------------------------+
|が| 304C |
|か| 304B |
+------+-----------------------------+
现在,我们在4.0.0 allkeystable 中搜索304B304C,并找到以下几行:
304 B; [462]#平假名 KA
304 C; [463] [464]#平假名 GA; QQCM
正式的 Unicode 名称(跟在#号之后)告诉我们日语音节(平假名),非正式分类(字母,数字或标点符号)和西方标识符(KAGA,它们恰好是浊音同一字母对的组件)。更重要的是,两行的主要权重(方括号内的第一个十六进制数字)均为1E57。为了进行搜索和排序比较,MySQL 仅关注主要权重,而忽略了所有其他数字。这意味着我们正在根据 Unicode 规范正确地对进行排序。如果要区分它们,则必须使用非 UCA(Unicode 排序算法)排序规则(utf8_binutf8_general_ci),或者比较HEX()的值,或使用ORDER BY CONVERT(s1 USING sjis)。当然,仅根据 Unicode 正确是不够的:提交该错误的人同样正确。为解决此问题,我们需要根据 JIS X 4061 标准对日语进行另一种校对,其中可以区分KA/GA之类的有声/无声字母对以进行 Order。
|
A.11.14. * |为什么 CJK 字符串在 Unicode 中排序不正确? (II)|
||> [!NOTE|label:Note]



对于 MySQL 8.0 之前的 MySQL 版本,可能会出现此处描述的 CJK 排序问题。从 MySQL 8.0 开始,可以使用utf8mb4字符集和utf8mb4_ja_0900_as_cs归类来解决它们。



如果您正在使用 Unicode(ucs2utf8),并且知道 Unicode 排序 Sequences 是什么(请参见第 A.11 节“ MySQL 5.7 FAQ:MySQL 中文,日文和韩 Literals 符集”),但是 MySQL 似乎仍然对 table 进行了不正确的排序,请首先验证 table 定义中的字符集:
mysql>显示创建 tablet\G
**** **** **** **** 1.行 **** **** **** **** **
Table: t
创建 table:CREATE TABLE t(
s1 char(1)CHARACTER SET ucs2 DEFAULT NULL
)ENGINE = MyISAM DEFAULT CHARSET = latin1
由于第s1列的字符集似乎正确(ucs2),因此请检查INFORMATION_SCHEMA.COLUMNStable 可以提供有关此列的哪些信息:
mysql> SELECT COLUMN_NAME,CHARACTER_SET_NAME,COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME ='s1'
AND TABLE_NAME ='t';
+-------------+--------------------+-----------------+
| COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME |
+-------------+--------------------+-----------------+
| s1 | ucs2 | ucs2_general_ci |
+-------------+--------------------+-----------------+
(有关更多信息,请参见第 24.5 节“ INFORMATION_SCHEMA COLUMNStable”。)
您可以看到排序规则是ucs2_general_ci而不是ucs2_unicode_ci。可以使用显示字符集找到这样做的原因,如下所示:
mysql> SHOW CHARSET like'ucs2%';
+---------+---------------+-------------------+--------+
|字符集|描述默认排序规则| Maxlen |
+---------+---------------+-------------------+--------+
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
+---------+---------------+-------------------+--------+
对于ucs2utf8,默认归类为“常规”。要指定 Unicode UCA 归类,请使用COLLATE ucs2_unicode_ci,如上一项所示。
|
**A.11.15. ** |为什么我的补充字符被 MySQL 拒绝?|
||补充字符位于 Unicode * Basic Multilingual Plane/Plane 0 *之外。 BMP 字符的代码点值介于U+0000U+FFFF之间。补充字符的代码点值介于U+10000U+10FFFF之间。
要存储补充字符,必须使用允许它们的字符集:
utf8ucs2字符集仅支持 BMP 字符。
utf8字符集仅允许使用UTF-8个字符(最多三个字节)。这导致了诸如在错误#12600 中发现的报告,我们将其拒绝为“不是错误”。使用utf8,当 MySQL 遇到无法理解的字节时,必须截断 Importing 字符串。否则,未知错误的多字节字符多长时间。
一种可能的解决方法是使用ucs2而不是utf8,在这种情况下,“坏”字符将更改为问号。但是,不会发生截断。您也可以将数据类型更改为BLOBBINARY,它们不执行有效性检查。
utf8mb4utf16utf16leutf32字符集支持 BMP 字符以及 BMP 之外的补充字符。
|
**A.11.16. ** |“ CJK”应为“ CJKV”吗?|
||否。术语“ CJKV”(日文,日文,韩文,越南文)是指包含汉字(原为中文)的越南字符集。 MySQL 支持使用西方字符的现代越南语脚本,但不支持使用汉字的老式越南语脚本。
从 MySQL 5.6 开始,存在 Unicode 字符集的越南语排序规则,如第 10.10.1 节“ Unicode 字符集”所述。
|
**A.11.17. ** | MySQL 是否允许在数据库和 table 名中使用 CJK 字符?|
||Yes.|
|
**A.11.18. ** |我在哪里可以找到 MySQL 手册的中文,日文和韩文翻译?|
||可以从https://dev.mysql.com/doc/下载 MySQL 5.6 手册的日语翻译。
|
**A.11.19. ** |在哪里可以获得有关 CJK 和 MySQL 相关问题的帮助?|
||以下资源可用:
可以在https://wikis.oracle.com/display/mysql/List+of+MySQL+User+Groups找到 MySQL 用户组的列 table。
http://tinyurl.com/y6xcuf查看与字符集问题有关的功能请求。
访问 MySQL 字符集,排序规则,Unicode 论坛http://forums.mysql.com/还提供外语论坛。|