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