[前][次][番号順一覧][スレッド一覧]

mysql:8950

From: <tamayanx@xxxxxxxxxx>
Date: 11 Mar 2004 15:17:02 +0900
Subject: [mysql 08950] Re: sjis & BLOB

仙石様
   アドバイス有り難うございました。しかし私には理解出来ません。
   物の本によるとaddslash()にて特殊文字をエスケープしなさい、
   と書かれていますが、addslash()をつけると日本語は全く表示
   されません。今少し色々テストしてみます。有り難うございました。
                  2004.3.11    松本



> 仙石と申します。既知の問題とは思いますが、あまり知られていない問題である
> ような気もしますので、まとめとして報告します。
> 
>     default-character-set=sjis としていると、
>     BLOB 型のデータを挿入/更新する時、
>     0x81 〜 0x9F ないし 0xE0 〜 0xFC の次に
>     エスケープ文字が来ても無視される
> 
> という問題が、MySQL サーバにあります。4.0.16, 4.0.18, 4.1.1 で確認しました。
> sjis だけでなく、症状から言って他のマルチバイト言語に共通する問題でしょう。
> 
> 次の perl スクリプトで簡単に検証できます:
> 
> ------------------------------------------------------------------------
> #!/usr/bin/perl
> for ($i=112; $i < 256; $i++) {
>     $sql .= sprintf(\"%c\\\\0\", $i);
> }
> $sql = \"INSERT INTO blobtest(data) VALUES (\'$sql\')\";
> 
> use DBI;
> $db_url = \"dbi:mysql:test:localhost\";
> $db_user = \'test\';
> $db_password = \'xxxxxxxx\';
> $dbh = DBI->connect($db_url, $db_user, $db_password,
> 		    { PrintError => 1, RaiseError => 0 });
> if (!defined($dbh)) {
>     print \"[NG] connect:\\t\" . $DBI::errstr;
>     exit 1;
> }
> $sth = $dbh->prepare($sql);
> if(!($rv = $sth->execute())){
>     print \"[NG] execute:\\t$rv:$dbh->err:$dbh->strrstr:$dbh->state\\n\";
>     exit(1);
> }
> ------------------------------------------------------------------------
> 
> このスクリプトを走らせると、
> 
>     ○\\0○\\0○\\0○\\0○\\0...  ( ○ は 0x70 〜 0xFF )
> 
> といった感じのデータを blobtest テーブルに挿入するわけですが、
> ○が、0x81 〜 0x9F ないし 0xE0 〜 0xFC の範囲にある文字の時だけ、
> その次の「\\」が通常の文字と解釈されてしまい、
> 「\\0」の部分が 0 という NULL 文字ではなく「\\0」という文字列として
> 挿入されてしまいます。
> 
> 症状から言って原因は明らかで、BLOB 型なのにリテラルを SJIS 文字列として
> 解釈してしまっているからでしょう。実際 4.0.x のソースコードでは、リテラ
> ルを default-character-set な文字列であると決めうちしてしまっています。
> 
> 4.1.x では、カラムごとに character-set を切り替えられるようですが、
> default-character-set=sjis していると、SJIS として解釈されてしまうようで
> す。_binary\'○\\0○\\0○\\0○\\0○\\0...\' とすればいけそうな気がしたのですが、
> 4.1.x の機能を私がまだあまり理解できていないためか、今のところうまくいっ
> てません。
> 
> BLOB って (どちらかと言えば) 敬遠されているような気配も感じますが ;-)、
> Java の場合は、NULL 文字等のエスケープを JDBC がやってくれるので、
> 
>     byte[] data;
>         ...
>     pstmt = con.prepareStatement(\"INSERT INTO blobtest(data) VALUES (?)\");
>         ...
>     pstmt.setBytes(1, data);
>     pstmt.execute();
> 
> などとそのまま setBytes できて簡単だし、(多少?) 遅いという欠点も BLOB 型
> カラムを検索キーにするわけじゃないので、更新頻度が高くなければ充分使える
> ものだと思っています。
> 
> ただ、上記のように default-character-set=sjis している場合は一筋縄にはい
> かないので、どうするのが一番スマートなのかと、悩んでいる今日このごろです。
> 
> 
> #8793.								仙石 浩明
> http://www.gcd.org/sengoku/		Hiroaki Sengoku <sengoku@xxxxxxxxxx>
> 


[前][次][番号順一覧][スレッド一覧]