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>
>