A.11.1.
|
MySQL で使用できる CJK
文字セットはどの文字セットですか。
|
|
CJK 文字セットのリストは、MySQL
のバージョンによって異なることがあります。たとえば、gb18030
文字セットは MySQL 5.7.4
より前はサポートされていませんでした。ただし、INFORMATION_SCHEMA.CHARACTER_SETS
表のすべてのエントリの DESCRIPTION
カラムには適用可能な言語の名前が表示されるため、次のクエリーを使用して
Unicode 以外のすべての CJK
文字セットの最新のリストを取得できます。
mysql> SELECT CHARACTER_SET_NAME, DESCRIPTION
-> FROM INFORMATION_SCHEMA.CHARACTER_SETS
-> WHERE DESCRIPTION LIKE '%Chin%'
-> OR DESCRIPTION LIKE '%Japanese%'
-> OR DESCRIPTION LIKE '%Korean%'
-> ORDER BY CHARACTER_SET_NAME;
+--------------------+---------------------------------+
| CHARACTER_SET_NAME | DESCRIPTION |
+--------------------+---------------------------------+
| big5 | Big5 Traditional Chinese |
| cp932 | SJIS for Windows Japanese |
| eucjpms | UJIS for Windows Japanese |
| euckr | EUC-KR Korean |
| gb18030 | China National Standard GB18030 |
| gb2312 | GB2312 Simplified Chinese |
| gbk | GBK Simplified Chinese |
| sjis | Shift-JIS Japanese |
| ujis | EUC-JP Japanese |
+--------------------+---------------------------------+
9 rows in set (0.01 sec)
(詳細は、セクション21.1「INFORMATION_SCHEMA CHARACTER_SETS テーブル」を参照してください。)
MySQL
は中華人民共和国の正式な文字セットである
GB 文字セット (Guojia
Biaozhun、National
Standard、または Simplified
Chinese) の 3 つのバリアント
(gb2312 、gbk 、および
gb18030 (MySQL 5.7.4
で追加されました)) をサポートしています。
ユーザーが gbk の文字を
gb2312
に挿入しようとすることがありますが、これはほとんどの場合動作します。gbk
は gb2312
のスーパーセットであるためです。ただし、より珍しい漢字を挿入しようとすると動作しません。(例については、Bug
#16072 を参照してください)。
ここでは、gb2312 または
gbk
で正当な文字を明らかにして、正式なドキュメントへの参照を示します。gb2312
または gbk
のバグを報告する前に、これらのリファレンスを確認してください。
|
A.11.2.
|
CJK
文字をテーブルに挿入しました。SELECT
でそれらが「?」文字として表示されるのはなぜですか。
|
|
この問題は、通常、アプリケーションプログラムまたはオペレーティングシステムの設定と
MySQL
の設定が一致していないことが原因です。これらのタイプの問題を修正するための一般的な手順を次に示します。
-
使用している MySQL
のバージョンを確認します。
これを判別するには、SELECT
VERSION();
ステートメントを使用します。
-
意図した文字セットがデータベースで実際に使用されていることを確認します。
ユーザーは多くの場合、クライアントの文字セットはサーバーの文字セットまたは表示のために使用される文字セットと常に同じであると考えます。ただし、これらは両方とも間違った想定です。SHOW
CREATE TABLE tablename
の結果をチェックするか、次のステートメントを使用することによって確認できます。
SELECT character_set_name, collation_name
FROM information_schema.columns
WHERE table_schema = your_database_name
AND table_name = your_table_name
AND column_name = your_column_name;
-
正しく表示されない文字の 16
進値を判別します。
テーブル table_name
のカラム column_name
のこの情報を取得するには、次のクエリーを使用します。
SELECT HEX(column_name)
FROM table_name;
3F は ?
文字のエンコードです。これは、?
が実際にカラムに格納される文字であることを意味します。これは、ほとんどの場合、特定の文字をクライアントの文字セットからターゲットの文字セットに変換するときの問題のために発生します。
-
ラウンドトリップが可能であることを確認します
(つまり、literal (または
_introducer hexadecimal-value )
を選択すると、結果として
literal
が取得される)。
たとえば、日本語のカタカナ文字
Pe (ペ )
はすべての CJK
文字セットに存在し、コードポイント値 (16
進コーディング) は 0x30da
です。この文字のラウンドトリップをテストするには、次のクエリーを使用します。
SELECT 'ペ' AS `ペ`; /* or SELECT _ucs2 0x30da; */
結果も「ペ」 ではない場合、ラウンドトリップは失敗しました。
そのような失敗に関するバグレポートの場合は、SELECT
HEX('ペ');
も試すように要請されることがあります。これにより、クライアントのエンコードが正しいかどうかを判断できます。
-
問題が MySQL
以外のブラウザまたはほかのアプリケーションの問題ではないことを確認します。
このタスクを行うには、mysql
クライアントプログラム (Windows の場合:
mysql.exe)
を使用します。mysql
では正しく表示されるが、アプリケーションでは表示されない場合、問題はシステム設定が原因である可能性があります。
設定を確認するには、次のような出力が表示される
SHOW VARIABLES
ステートメントを使用します。
mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
8 rows in set (0.03 sec)
これらは、西洋諸国のサーバー
(latin1
は西ヨーロッパ文字セットであり、MySQL
のデフォルトです)
に接続される国際業務用のクライアントの典型的な文字セット設定です
(utf8 Unicode
が使用されています)。
Latin よりも Unicode (通常、Unix での
utf8 バリアント、および Windows
での ucs2 バリアント)
の方が望ましいですが、オペレーティングシステムのユーティリティーで最適にサポートされる文字セットではないことがあります。多くの
Windows ユーザーは、Microsoft の文字セット
(日本語 Windows 用の cp932 など)
が適当であると判断します。
サーバーの設定を制御できず、基盤となっているコンピュータがわからない場合は、自分の国の一般的な文字セットに変更することを試してください
(euckr =
韓国、gb18030 、gb2312 、または
gbk =
中華人民共和国、big5 =
台湾、sjis 、ujis 、cp932 、または
eucjpms =
日本、ucs2 または
utf8 =
すべての国)。通常、クライアント、接続、および結果の設定のみを変更する必要があります。この
3
つを一度にすべて変更する簡単なステートメントがSET
NAMES です。例:
SET NAMES 'big5';
設定が正しい場合は、my.cnf
または my.ini
を編集することによってそれを永続的なものにできます。たとえば、次のような行を追加できます。
[mysqld]
character-set-server=big5
[client]
default-character-set=big5
アプリケーションで使用されている API
構成の設定に問題があることもあります。詳細は、「GUI
フロントエンドまたはブラウザで CJK
文字が正しく表示されないのはなぜですか」を参照してください。
|
A.11.3.
|
Big5
中国語文字セットを使用する場合は、どのような問題に注意するべきですか。
|
|
MySQL は、香港および台湾 (中華民国) で一般的な
Big5 文字セットをサポートしています。MySQL の
big5 は、実際には、本来の
big5 文字セットと非常に似ている
Microsoft コードページ 950
です。この文字セットは
MySQL バージョン 4.1.16 / 5.0.16
以降で変更されています (Bug #12476
のため)。たとえば、次のステートメントは最新のバージョンの
MySQL
では動作しますが、古いバージョンでは動作しません。
mysql> CREATE TABLE big5 (BIG5 CHAR(1) CHARACTER SET BIG5);
Query OK, 0 rows affected (0.13 sec)
mysql> INSERT INTO big5 VALUES (0xf9dc);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM big5;
+------+
| big5 |
+------+
| 嫺 |
+------+
1 row in set (0.02 sec)
HKSCS
拡張を追加する機能要求は申請されています。この拡張を必要とするユーザーの場合、Bug
#13577
のための推奨パッチが役に立つことがあります。
|
A.11.4.
|
日本語文字セットの変換が失敗するのはなぜですか。
|
|
MySQL
は、sjis 、ujis 、cp932 、および
eucjpms 文字セットと Unicode
をサポートしています。一般的なニーズは文字セット間で変換を行うことです。たとえば、Unix
のサーバー (通常は sjis または
ujis が使用されます) と Windows
のクライアント (通常は cp932
が使用されます)
を使用している場合があります。
次の変換表で、ucs2
カラムは変換前を表し、sjis 、cp932 、ujis 、および
eucjpms
カラムは変換後を表しています。つまり、後ろの
4
つのカラムは、CONVERT(ucs2)
を使用するか、値が含まれている
ucs2 カラムを
sjis 、cp932 、ujis 、または
eucjpms カラムに割り当てたときの
16 進数の結果を示しています。
では、この表の次の部分について考えてみましょう。
これは、MySQL が NOT SIGN (Unicode の
U+00AC ) を sjis
のコードポイント 0x81CA および
cp932 のコードポイント
3F に変換することを意味します
(3F は疑問符 (「?」)
であり、変換を実行できないときに常に使用される文字です)。
|
A.11.5.
|
SJIS の 81CA を cp932
に変換する場合はどうすればよいですか。
|
|
答えは「?」です。これについては深刻な苦情が寄せられています。多くのユーザーは、sjis
の 81CA (NOT SIGN) が
cp932 の 81CA (FULLWIDTH NOT
SIGN)
になるような「緩い」変換を望んでいます。この動作に変更することが検討されています。
|
A.11.6.
|
MySQL では円 (¥ )
記号をどのように表しますか。
|
|
いくつかのバージョンの日本語文字セット
(sjis および euc
の両方) では 5C
がリバースソリダス
(\ 。バックスラッシュとも呼ばれます)
として扱われ、ほかの文字セットでは円記号
(¥ )
として扱われるため、問題が発生します。
MySQL は JIS (Japanese Industrial Standards)
標準に記述されている 1
つのバージョンのみに従っています。MySQL では
5C
は常にリバースソリダス
(\ ) です。
|
A.11.7.
|
MySQL
で韓国語文字セットを使用する場合に注意する問題はありますか。
|
|
理論的には、複数のバージョンの
euckr (Extended Unix Code
Korea)
文字セットがありますが、認識されている問題は
1 つだけです。
コードポイント 0x5c
がウォン記号 (₩ )
である EUC-KR
の「KS-Roman」バリアントではなく、コードポイント
0x5c がリバースソリダス
(つまり、\ ) である EUC-KR
の「ASCII」バリアントが使用されています。これは、Unicode
の U+20A9 を euckr
に変換できないことを意味します。
mysql> SELECT
-> CONVERT('₩' USING euckr) AS euckr,
-> HEX(CONVERT('₩' USING euckr)) AS hexeuckr;
+-------+----------+
| euckr | hexeuckr |
+-------+----------+
| ? | 3F |
+-------+----------+
1 row in set (0.00 sec)
|
A.11.8.
|
なぜ「Incorrect string
value」というエラーメッセージが表示されるのですか。
|
|
説明のために、1 つの Unicode (ucs2 )
カラムおよび 1 つの中国語 (gb2312 )
カラムを持つテーブルを作成します。
mysql> CREATE TABLE ch
-> (ucs2 CHAR(3) CHARACTER SET ucs2,
-> gb2312 CHAR(3) CHARACTER SET gb2312);
Query OK, 0 rows affected (0.05 sec)
両方のカラムに珍しい文字「汌」 を挿入することを試みます。
mysql> INSERT INTO ch VALUES ('A汌B','A汌B');
Query OK, 1 row affected, 1 warning (0.00 sec)
警告が報告されました。次のステートメントを使用してその内容を確認します。
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1366
Message: Incorrect string value: '\xE6\xB1\x8CB' for column 'gb2312' at row 1
1 row in set (0.00 sec)
gb2312
カラムのみに関する警告でした。
mysql> SELECT ucs2,HEX(ucs2),gb2312,HEX(gb2312) FROM ch;
+-------+--------------+--------+-------------+
| ucs2 | HEX(ucs2) | gb2312 | HEX(gb2312) |
+-------+--------------+--------+-------------+
| A汌B | 00416C4C0042 | A?B | 413F42 |
+-------+--------------+--------+-------------+
1 row in set (0.00 sec)
いくつかのことを説明する必要があります。
「エラー」ではなく「警告」であることが
MySQL
の特徴です。あきらめずにできることをして最善の結果を得ることが試みられます。
「汌」 という文字は
gb2312
文字セットにありません。この問題については前に説明しました。
古いバージョンの MySQL
を使用している場合は、別のメッセージが表示される可能性があります。
sql_mode=TRADITIONAL
を設定している場合は、警告ではなくエラーメッセージが表示されます。
|
A.11.9.
|
Access、PHP、またはその他の API
を使用したアプリケーションの GUI
フロントエンドまたはブラウザで、CJK
文字が正しく表示されないのはなぜですか。
|
|
mysql クライアント (Windows:
mysql.exe)
を使用してサーバーに直接接続し、同じクエリーをそこで試してください。mysql
が正常に応答する場合、問題はアプリケーションインタフェースで初期化が必要であることである可能性があります。mysql
で SHOW VARIABLES LIKE 'char%';
ステートメント使用して、使用される文字セットを確認します。Access
を使用している場合は、Connector/ODBC
を使用して接続することがほとんどです。この場合は、Configuring Connector/ODBCを確認してください。たとえば、big5
を使用している場合は、SET NAMES
'big5'
と入力します。(この場合「;」 は必要ありません)。ASP
を使用している場合は、コードに SET
NAMES
を追加する必要があることがあります。過去に作成された例を次に示します。
<%
Session.CodePage=0
Dim strConnection
Dim Conn
strConnection="driver={MySQL ODBC 3.51 Driver};server=server;uid=username;" \
& "pwd=password;database=database;stmt=SET NAMES 'big5';"
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open strConnection
%>
同様に、Connector/Net で latin1
以外の文字セットを使用している場合は、接続文字列に文字セットを指定する必要があります。詳細は、Connector/NET Connectionsを参照してください。
PHP
を使用している場合は、次のコードを試してください。
<?php
$link = mysql_connect($host, $usr, $pwd);
mysql_select_db($db);
if( mysql_error() ) { print "Database ERROR: " . mysql_error(); }
mysql_query("SET NAMES 'utf8'", $link);
?>
この場合、SET NAMES を使用して
character_set_client 、character_set_connection 、および
character_set_results
を変更しています。
mysql ではなく、新しい
mysqli
拡張を使用することをお勧めします。mysqli
を使用する場合は、前の例を次のように書き直すことができます。
<?php
$link = new mysqli($host, $usr, $pwd, $db);
if( mysqli_connect_errno() )
{
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$link->query("SET NAMES 'utf8'");
?>
PHP
アプリケーションで頻繁に発生する別の問題は、ブラウザによって行われる想定に関連しています。<meta>
タグを追加または変更するだけでこの問題が修正されることがあります。たとえば、ユーザーエージェントがページの内容を
UTF-8
として解釈するようにするには、HTML ページの
<head> に <meta
http-equiv="Content-Type" content="text/html;
charset=utf-8"> を含めてください。
Connector/J
を使用している場合は、Using Character Sets and Unicodeを参照してください。
|
A.11.10.
|
MySQL 5.6
にアップグレードしました。文字セットに関して、MySQL
4.0 の動作に戻すにはどうすればよいですか。
|
|
MySQL バージョン 4.0
では、サーバーおよびクライアントの両方のための単一の「グローバル」文字セットがあり、使用する文字の決定はサーバー管理者が行なっていました。これは
MySQL バージョン 4.1
以降で変更されました。現在行われるのは、セクション10.1.4「接続文字セットおよび照合順序」に説明されているように、「ハンドシェイク」です。
クライアントが接続するときに、使用する文字セットの名前をサーバーに送信します。サーバーはこの名前を使用して、character_set_client 、character_set_results 、および
character_set_connection
システム変数を設定します。実際には、サーバーは文字セット名を使用して
SET NAMES 操作を実行します。
このことの影響は、--character-set-server=utf8
を指定して mysqld
を開始することによって、クライアントの文字セットを制御できないことです。ただし、アジア地域には
MySQL 4.0
の動作が望ましいという顧客がいます。この動作を維持できるように、--skip-character-set-client-handshake
を使用してオフにできる mysqld
スイッチ
--character-set-client-handshake
が追加されました。--skip-character-set-client-handshake
を指定して mysqld
を起動すると、クライアントが接続するときに、使用する文字セットの名前がサーバーに送信されますが、サーバーはクライアントからのこの要求を無視します。
例として、望ましいサーバーの文字セットが
latin1 であるとします (CJK
地域ではあまりないことですが、これはデフォルト値です)。クライアントのオペレーティングシステムでサポートされている文字セットであるため、クライアントが
utf8
を使用しているとします。latin1
をデフォルトの文字セットとしてサーバーを起動します。
mysqld --character-set-server=latin1
そのあと、クライアントをデフォルトの文字セット
utf8 で起動します。
mysql --default-character-set=utf8
現在の設定は、SHOW
VARIABLES
の出力を表示することによって確認できます。
mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
8 rows in set (0.01 sec)
クライアントを停止し、mysqladmin
を使用してサーバーを停止します。今度はハンドシェイクをスキップするように通知して、サーバーをふたたび起動します。
mysqld --character-set-server=utf8 --skip-character-set-client-handshake
クライアントをデフォルトの文字セットとして
utf8
をふたたび指定して起動し、現在の設定を表示します。
mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+----------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------------+
8 rows in set (0.01 sec)
SHOW VARIABLES
の異なる結果を比較することによって確認できるように、--skip-character-set-client-handshake
が使用された場合、サーバーはクライアントの初期設定を無視します。
|
A.11.11.
|
CJK 文字での LIKE
検索および FULLTEXT
検索が失敗することがあるのはなぜですか。
|
|
BINARY カラムおよび
BLOB カラムに対する
LIKE
検索には非常に単純な問題があります。文字の終わりを判別する必要があることです。マルチバイト文字セットでは、各文字のオクテット長が異なることがあります。たとえば、utf8
の場合、次に示すように A は 1
バイトを必要としますが、ペ は 3
バイトを必要とします。
+-------------------------+---------------------------+
| OCTET_LENGTH(_utf8 'A') | OCTET_LENGTH(_utf8 'ペ') |
+-------------------------+---------------------------+
| 1 | 3 |
+-------------------------+---------------------------+
1 row in set (0.00 sec)
最初の文字の終わりを判別できなければ、2
番目の文字が始まる位置を判別できません。この場合、LIKE
'_A%'
などの非常に単純な検索が失敗します。解決策は、通常の
CJK
文字セットを最初から使用するか、比較する前に
CJK 文字を変換することです。
これは、存在しない文字のエンコードを MySQL
が許可できない理由の 1
つです。不正な入力を厳密に拒否しなければ、文字の終わりを判別する方法がありません。
FULLTEXT
検索の場合は、単語の始まりと終わりを判別する必要があります。西洋の言語の場合、それらのほとんど
(すべてでなければ)
が簡単に識別できる単語の境界 (スペース文字)
を使用しているため、これが問題となることはほとんどありません。ただし、通常、アジアの言語ではこれは異なります。独自の判断で不完全な方法を使用して、すべての漢字が単語を表すと想定したり、(日本語の場合)
文法的な終わりに従ったカタカナからひらがなへの変化に応じるようにしたりすることもできます。ただし、唯一の確実な解決策では、包括的な単語のリストが必要となります。これは、サポートされる各アジア言語のサーバーに辞書を含める必要があることを意味します。これは簡単に言って実現可能ではありません。
|
A.11.12.
|
文字 X
がすべての文字セットで使用可能であるかどうかを判別するにはどうすればよいですか。
|
|
簡体字中国語および半角ではない基本的な日本語のかな文字のほとんどは、すべての
CJK
文字セットで表示されます。次のストアドプロシージャーは、UCS-2
Unicode
文字を受け入れて、それをほかのすべての文字セットに変換し、結果を
16 進数で表示します。
DELIMITER //
CREATE PROCEDURE p_convert(ucs2_char CHAR(1) CHARACTER SET ucs2)
BEGIN
CREATE TABLE tj
(ucs2 CHAR(1) character set ucs2,
utf8 CHAR(1) character set utf8,
big5 CHAR(1) character set big5,
cp932 CHAR(1) character set cp932,
eucjpms CHAR(1) character set eucjpms,
euckr CHAR(1) character set euckr,
gb2312 CHAR(1) character set gb2312,
gbk CHAR(1) character set gbk,
sjis CHAR(1) character set sjis,
ujis CHAR(1) character set ujis);
INSERT INTO tj (ucs2) VALUES (ucs2_char);
UPDATE tj SET utf8=ucs2,
big5=ucs2,
cp932=ucs2,
eucjpms=ucs2,
euckr=ucs2,
gb2312=ucs2,
gbk=ucs2,
sjis=ucs2,
ujis=ucs2;
/* If there is a conversion problem, UPDATE will produce a warning. */
SELECT hex(ucs2) AS ucs2,
hex(utf8) AS utf8,
hex(big5) AS big5,
hex(cp932) AS cp932,
hex(eucjpms) AS eucjpms,
hex(euckr) AS euckr,
hex(gb2312) AS gb2312,
hex(gbk) AS gbk,
hex(sjis) AS sjis,
hex(ujis) AS ujis
FROM tj;
DROP TABLE tj;
END//
入力は、単一の ucs2
文字、またはその文字のコードポイント値 (16
進表記) です。たとえば、ucs2
のエンコードおよび名前についての Unicode
のリスト
(http://www.unicode.org/Public/UNIDATA/UnicodeData.txt)
から、カタカナ文字 Pe
はすべての CJK
文字セットにあり、コードポイント値が
0x30da
であることがわかります。この値を
p_convert()
の引数として使用すると、次のような結果となります。
mysql> CALL p_convert(0x30da)//
+------+--------+------+-------+---------+-------+--------+------+------+------+
| ucs2 | utf8 | big5 | cp932 | eucjpms | euckr | gb2312 | gbk | sjis | ujis |
+------+--------+------+-------+---------+-------+--------+------+------+------+
| 30DA | E3839A | C772 | 8379 | A5DA | ABDA | A5DA | A5DA | 8379 | A5DA |
+------+--------+------+-------+---------+-------+--------+------+------+------+
1 row in set (0.04 sec)
カラム値が 3F
(つまり、疑問符文字 (? ))
であるカラムがないため、すべての変換が正常に行われたことがわかります。
|
A.11.13.
|
CJK 文字列が Unicode
で間違ってソートされるのはなぜですか。(I)
|
|
utf8_unicode_ci 検索や
ucs2_unicode_ci 検索、または
ORDER BY
ソートの結果が、母国語のユーザーが予期する結果ではないことがあります。バグである可能性を除外するわけではありませんが、多くのユーザーは
Unicode Collation Algorithm
の標準表のウェイトを正しく読んでいないことが過去に判明しました。MySQL
は
http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt
にある表を使用しています。これは、unicode.org
のホームページからナビゲートすることによって見つかる最初の表ではありません。MySQL
はより新しい 4.1.0 の 「allkeys」
表ではなく、古い 4.0.0
の表を使用しているためです。(MySQL 5.6
の新しい '520' 照合順序では、5.2
の 「allkeys」
表が使用されています。)これは、次に示した
Bug #16526
で報告されたような状況が発生しないように、インデックスに影響する順序付けの変更に非常に慎重であるためです。
mysql< CREATE TABLE tj (s1 CHAR(1) CHARACTER SET utf8 COLLATE utf8_unicode_ci);
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO tj VALUES ('が'),('か');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tj WHERE s1 = 'か';
+------+
| s1 |
+------+
| が |
| か |
+------+
2 rows in set (0.00 sec)
最初の結果行の文字は、検索した文字ではありません。MySQL
でその文字が取得されたのはなぜでしょうか。まず、Unicode
のコードポイント値を確認します。これを行うには、ucs2
バージョンの文字の 16 進数を表示します。
mysql> SELECT s1, HEX(CONVERT(s1 USING ucs2)) FROM tj;
+------+-----------------------------+
| s1 | HEX(CONVERT(s1 USING ucs2)) |
+------+-----------------------------+
| が | 304C |
| か | 304B |
+------+-----------------------------+
2 rows in set (0.03 sec)
4.0.0 allkeys 表で 304B
および 304C
を探すと、これらの行が見つかります。
304B ; [.1E57.0020.000E.304B] # HIRAGANA LETTER KA
304C ; [.1E57.0020.000E.304B][.0000.0140.0002.3099] # HIRAGANA LETTER GA; QQCM
正式な Unicode 名 (「#」
マークの後ろにあります) は、日本語の五十音
(ひらがな)、非公式な区分
(文字、数字、または句読点)、西洋言語での識別子
(KA または
GA 。これは、たまたま同じ文字のペアの有声音および無声音となっています)
を示しています。さらに重要なのは、プライマリウェイト
(角括弧の中の最初の 16 進数) が両方の行で
1E57
となっていることです。検索とソートの両方の比較で、MySQL
はプライマリウェイトのみに注意を払って、ほかのすべての数値を無視します。これは、「が」 および「か」 が
Unicode
の仕様に従って正しくソートされていることを意味します。これらを区別するには、UCA
(Unicode Collation Algorithm) 以外の照合順序
(utf8_bin または
utf8_general_ci )
を使用するか、HEX()
値を比較するか、ORDER BY CONVERT(s1 USING
sjis)
を使用する必要があります。もちろん、「Unicode
に従えば」正しいだけでは十分ではなく、バグを報告したユーザーも同様に正しいと言えます。KA /GA
のような有声音/無声音文字のペアを順序付けのために区別できる、JIS
X 4061
標準に従った別の日本語の照合順序を追加する計画があります。
|
A.11.14.
|
CJK 文字列が Unicode
で間違ってソートされるのはなぜですか。(II)
|
|
Unicode (ucs2 または
utf8 ) を使用していて、Unicode
のソート順がわかっているが
(セクションA.11「MySQL 5.6 FAQ: MySQL の中国語、日本語、および韓国語の文字セット」を参照してください)、MySQL
でテーブルが間違ってソートされているように見える場合は、まずテーブルの文字セットを確認してください。
mysql> SHOW CREATE TABLE t\G
******************** 1. row ******************
Table: t
Create Table: CREATE TABLE `t` (
`s1` char(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
文字セットは正しいように見えるため、このカラムに関して
INFORMATION_SCHEMA.COLUMNS
テーブルで表示できる情報を確認します。
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 |
+-------------+--------------------+-----------------+
1 row in set (0.01 sec)
(詳細は、セクション21.4「INFORMATION_SCHEMA COLUMNS テーブル」を参照してください。)
照合順序が ucs2_unicode_ci ではなく
ucs2_general_ci
であることがわかります。このようになる理由は、次のように
SHOW CHARSET
を使用して見つけることができます。
mysql> SHOW CHARSET LIKE 'ucs2%';
+---------+---------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+---------------+-------------------+--------+
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
+---------+---------------+-------------------+--------+
1 row in set (0.00 sec)
ucs2 および utf8
の場合、デフォルトの照合順序は
「general」 です。Unicode
の照合順序を指定するには、COLLATE
ucs2_unicode_ci を使用します。
|
A.11.15.
|
補助文字が MySQL で拒否されるのはなぜですか。
|
|
MySQL 5.5.3 より前では、MySQL は補助文字
(つまり、UTF-8 で 3
バイトを超えるサイズを必要とする文字)
をサポートしていません。Unicode
で基本多言語面/第 0
面と呼ばれているもののみがサポートされます。いくつかの非常に珍しい漢字のみが補助文字となっています。それらに対するサポートは一般的ではありません。このことが
Bug #12600
などで報告され、「バグではありません」として拒否されました。utf8
では、理解できないバイトが出現した場合に、入力文字列を切り捨てる必要があります。そうしないと、不正なマルチバイト文字の長さがわかりません。
考えられる 1 つの回避策は、utf8
の代わりに ucs2
を使用することです。この場合、「不正な」文字は疑問符に置き換えられますが、切り捨ては行われません。妥当性チェックが行われない
BLOB または
BINARY
にデータ型を変更することもできます。
MySQL 5.5.3 の時点では、追加の Unicode 文字セット
utf16 、utf32 、および
4 バイトの utf8mb4 によって Unicode
のサポートが拡張され、補助文字が含まれるようになりました。これらの文字セットでは、基本多言語面
(BMP) の外にある補助 Unicode
文字がサポートされます。
|
A.11.16.
|
「CJKV」にするべきではありませんか。
|
|
いいえ。用語「CJKV」(Chinese
Japanese Korean Vietnamese) は漢字
(もともとは中国語)
が含まれているベトナム文字セットを指しています。MySQL
では、漢字を使用した古いベトナム文字をサポートする計画はありません。MySQL
では、西洋文字を使用する現代のベトナム文字はもちろんサポートされます。
MySQL 5.6
の時点では、セクション10.1.14.1「Unicode 文字セット」で説明しているように、Unicode
文字セットにベトナム語の照合順序があります。
|
A.11.17.
|
MySQL では CJK
文字をデータベース名およびテーブル名に使用できますか。
|
|
この問題は、対応するディレクトリおよびファイルの名前を自動的に書き換えることによって、MySQL
5.1 で修正されました。
たとえば、オペレーティングシステムでディレクトリ名に
CJK
がサポートされないサーバーに「楮」 という名前のデータベースを作成した場合、MySQL
は E6A5AE
(つまり、「楮」 文字の Unicode の
16 進表現) を特殊な方法でエンコードした
@0w@00a5@00ae
という名前のディレクトリが作成されます。ただし、SHOW
DATABASES
ステートメントを実行すると、データベースが「楮」 として示されます。
|
A.11.18.
|
MySQL
マニュアルの中国語版、日本語版、および韓国語版はどこにありますか。
|
|
MySQL 5.1.12
の簡体字中国語版のマニュアルは、http://dev.mysql.com/doc/にあります。MySQL
4.1
マニュアルの日本語版は、http://dev.mysql.com/doc/
からダウンロードできます。
|
A.11.19.
|
MySQL での CJK
および関連する問題についての支援はどこで受けることができますか。
|
|
次のリソースを利用できます。
|