Open Source WEB

REPLACE()で、普通の日本語文字列(eucjpms,cp932,utf8など)と、 binary文字列が3つのパラメータに混在していたとき、 結果の文字列がbinaryになることは分かった。

さて、唐突であるが、次のREPLACE()を考えてみよう。

mysql> SET NAMES eucjpms;
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT REPLACE('東京理科大学','並','Physics');
+----------------------------------------+
| REPLACE('東京理科大学','並','Physics') |
+----------------------------------------+
| 東京理科大学                           |
+----------------------------------------+
1 row in set (0.00 sec)
 
mysql>

'東京理科大学'という文字列の中には、'並'という文字列は存在しないので 置換は行なわれず、'Physics' という文字列は出力には現われない。

さて、ここで、最後のPhysicsだけをbinaryにしてみよう。

mysql> SELECT REPLACE('東京理科大学','並',_binary'Physics');
+-----------------------------------------------+
| REPLACE('東京理科大学','並',_binary'Physics') |
+-----------------------------------------------+
| 東京理?Physics膤?                             |
+-----------------------------------------------+
1 row in set (0.00 sec)
 
mysql>

すると、何だか置換が行なわれたようだ。 それも、何だか無理矢理行なったようで、文字の一部が壊れているようだ。

さて、'東京理科大学'というマルチバイト文字列の中には、 '並'という文字列は当然含まれていないので、置換されるのは変である。 ということは、この比較を行なう前に、実は全てのパラメータはbinary に変換されてしまい、そののちREPLACE()が実行されたのではないだろうか。

つまり、1つでもbinaryがあれば、

mysql> SELECT REPLACE(_binary'東京理科大学',_binary'並',_binary'Physics');
+-------------------------------------------------------------+
| REPLACE(_binary'東京理科大学',_binary'並',_binary'Physics') |
+-------------------------------------------------------------+
| 東京理?Physics膤?                                           |
+-------------------------------------------------------------+
1 row in set (0.00 sec)
 
mysql>

と同じと考えて良いように思うがどうだろう。

REPLACE()は、 処理を始める前に、全てのパラメータが、結果のキャラクタセットに変換される。

ということらしい。

もちろん、

mysql> SELECT REPLACE(_binary'東京理科大学','並','Physics');
+-----------------------------------------------+
| REPLACE(_binary'東京理科大学','並','Physics') |
+-----------------------------------------------+
| 東京理?Physics膤?                             |
+-----------------------------------------------+
1 row in set (0.00 sec)
 
mysql> SELECT REPLACE('東京理科大学',_binary'並','Physics');
+-----------------------------------------------+
| REPLACE('東京理科大学',_binary'並','Physics') |
+-----------------------------------------------+
| 東京理?Physics膤?                             |
+-----------------------------------------------+
1 row in set (0.01 sec)
 
mysql>

となるのは予想通りである。


'東京理科大学'の中に'並'が存在する理由

この理由を調べるには、2つの文字列をHEX()を使って16進数表示してみればよい。

mysql> SELECT HEX('東京理科大学'), HEX('並');
+--------------------------+-----------+
| HEX('東京理科大学')      | HEX('並') |
+--------------------------+-----------+
| C5ECB5FECDFDB2CAC2E7B3D8 | CAC2      |
+--------------------------+-----------+
1 row in set (0.00 sec)
 
mysql>

CAC2 という並びが、'東京理科大学' の中に存在するのが分かるだろう。 CA は'科'の第2バイト、C2は'大'の第1バイトである。

そして、binaryになってしまったら、マルチバイト処理は無視されて、 バイト単位の処理になってしまうので、binaryの'並'は'東京理科大学' の中に存在することになる。

mysql> SELECT HEX(REPLACE('東京理科大学','並',_binary'Physics')), HEX('Physics');
+----------------------------------------------------+----------------+
| HEX(REPLACE('東京理科大学','並',_binary'Physics')) | HEX('Physics') |
+----------------------------------------------------+----------------+
| C5ECB5FECDFDB250687973696373E7B3D8                 | 50687973696373 |
+----------------------------------------------------+----------------+
1 row in set (0.00 sec)
 
mysql>

つまり、

マルチバイト文字列処理が、binary文字列処理をされると、 奇怪なことになることがある。

ということをしっかり記憶しておこう。

こういう分析に慣れておくと、日本語を扱っているときに奇妙な現象が発生しても、 うまく手なずけることができるようになるかもネ。


戻る:キャラクタセットがbinaryの文字列のREPLACEは

次へ:eucjpms,cp932,utf8混在のREPLACEは


フィードバック:

Name:
Comment:

There is no comment.

このサイトは、 IPA の「平成15年度オープンソフトウエア活用基盤整備事業」 の委託事業として開発されたKahuaで試験的に運用しております。

Copyright (c) 2004-2007 株式会社タイムインターメディア About Us