Open Source WEB

キャラクタセットを指定しても binary になってしまうことが分かった。 こういう時は本家のサイトを調べるべきである。 MySQL Lists(メーリングリスト)バグ情報などを調べる必要があろう。

バグ情報の中の 1/10に登録された CHARACTER SET still not working in stored functionsによると、

ファンクションは、戻り値のキャラクタセットに utf8 をしているにも拘らず、 binaryになっている。そして、プロシージャの方で、OUT により出力指定した パラメーターのキャラクタセットは、ちゃんとutf8になっているとのことだ。 バージョンは、5.0.19-BK, 5.0.18 でこのバグが確認されている。

ということで、まだ5.0.18に対してマニュアルに加えられたことは、 実は動いていないらしい。 つまり、

文字型のファンクションのキャラクタセットは、勝手にbinaryになる

ということだ。これはバグで、対応してくれるようだ。


今すぐに使うには、どうすれば良いか

正しく動かないけれども、それでも今すぐにファンクションで 日本語文字列を返したい場合、どうすれば良いだろうか。

ここで、逆転の発想をしてみよう。

キャラクタセットとして、binaryを指定してみよう。

どのキャラクタセットであっても、binaryに変換するときには、 文字列そのもの、要するにバイト列の内容は変らないのを憶えているだろうか。 binaryにすることで、予期しないキャラクタセットの変換がかかっていたのを、 止めさせようという魂胆である。

mysql> DROP FUNCTION IF EXISTS hello;
Query OK, 0 rows affected (0.20 sec)
 
mysql> DELIMITER //
mysql> CREATE FUNCTION hello() RETURNS VARCHAR(50) CHARACTER SET binary
    -> DETERMINISTIC RETURN 'こんにちは';
    -> //
Query OK, 0 rows affected (0.01 sec)
 
mysql> DELIMITER ;
mysql>

では、hello() をSELECTして確認してみよう。

mysql> SELECT hello();
+------------+
| hello()    |
+------------+
| こんにちは |
+------------+
1 row in set (0.05 sec)
 
mysql> SELECT CHARSET(hello());
+------------------+
| CHARSET(hello()) |
+------------------+
| binary           |
+------------------+
1 row in set (0.00 sec)
 
mysql>

binaryになっているが、ちゃんと表示ができている。

もうちょっと、複雑な使い方をしてみよう。

mysql> SELECT CONCAT('東京より、',hello(), '、MySQLだよ' );
+----------------------------------------------+
| CONCAT('東京より、',hello(), '、MySQLだよ' ) |
+----------------------------------------------+
| 東京より、こんにちは、MySQLだよ              |
+----------------------------------------------+
1 row in set (0.00 sec)
 
mysql>

でも、hello() がbinaryなので、

mysql> SELECT CHARSET(CONCAT('東京より、',hello(), '、MySQLだよ' ));
+-------------------------------------------------------+
| CHARSET(CONCAT('東京より、',hello(), '、MySQLだよ' )) |
+-------------------------------------------------------+
| binary                                                |
+-------------------------------------------------------+
1 row in set (0.00 sec)
 
mysql> 

CONCATした結果のキャラクタセットはbinaryになってしまう。 これを避けるには、hello()に対して、CONVERT関数により本来のキャラクタセット に変換してしまえば、以下のように全体のキャラクタセットも正常なものになる。

mysql> SELECT CHARSET(CONCAT('東京より、',CONVERT(hello() USING eucjpms),'、MySQLだよ'));
+----------------------------------------------------------------------------+
| CHARSET(CONCAT('東京より、',CONVERT(hello() USING eucjpms),'、MySQLだよ')) |
+----------------------------------------------------------------------------+
| eucjpms                                                                    |
+----------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>

しかし、さすがにこんな書き方はしたくないものだ。 あくまでも、今すぐに何とか使いたいという場合の 苦肉の策、急場しのぎ、誤魔化しである。

この問題は、日本語だけでなく、あらゆる言語で色々影響があるので、 近々直るのではないかと思う。直ったところで、再訪しようかと思う。


戻る:戻り値のキャラクタセットを指定せねば

次へ:文字列パラメータを与えてみよう


フィードバック:

Name:
Comment:

There is no comment.

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

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