SQLite Tips(sjis)
カテゴリー: ぷろぐらみんぐ/データベース
2006-09-19
SQLite Tips(sjis)
作成:2006.0915
編集:2006.09.15
【SQL】 | |||||||||||||||||||||||||||||||||
文字化け | |||||||||||||||||||||||||||||||||
【現象】 shift-jisやeucで データに標準関数を使用すると 予期せぬ 文字化けを誘発します。
|
|||||||||||||||||||||||||||||||||
例 | SELECT '新',lower('新');
|
||||||||||||||||||||||||||||||||
例 | SELECT '新品', substr('新品', 1, 1),substr('表', 1, 1);
|
||||||||||||||||||||||||||||||||
例 | SELECT like('_\','表'), '表' like '_\'
|
||||||||||||||||||||||||||||||||
まとめ |
・likeの動作が説明書と違う。 式 like 文字列式 like(文字列式, 式,) ※ like(x,y) : 実行すると説明書と位置が逆<like(y,x)>。 誤実装? 誤植? |
||||||||||||||||||||||||||||||||
sqlite/lang_expr.html にも書いてありますが、 A bug: SQLite only understands upper/lower case for 7-bit Latin characters. LIKE operator is case sensitive for 8-bit iso8859 characters or UTF-8 characters. |
|||||||||||||||||||||||||||||||||
そういうことで、utf8でデータを操作した方が無難ですね。 | |||||||||||||||||||||||||||||||||
確認用コード | |||||||||||||||||||||||||||||||||
php5 | <?php $charsetlist = array('sjis'=>'shift_jis', 'utf-8'=>'utf-8', 'euc-jp'=>'euc-jp'); $charset = 'sjis'; switch ($_GET['charset']) { case 'utf-8': $charset = 'utf-8'; break; case 'euc-jp': $charset = 'euc-jp'; break; case 'sjis': $charset = 'sjis'; break; default: $charset = ''; break; } ?> <html> <head> <?php echo sprintf('<meta http-equiv="Content-Type" content="text/html; charset=%s;"' , $charset ? $charsetlist[$charset] : 'shift_jis'); echo sprintf('<title>%s</title>' , $charset ? $charsetlist[$charset] : 'shift_jis'); ?> </head> <?php if (!$charset) { $uri = $_SERVER["SCRIPT_NAME"]; print '<frameset rows="*,30%,30%">'."\n"; print sprintf('<frame name="top" src="%s">', $uri.'?charset=sjis')."\n"; print sprintf('<frame name="bottom" src="%s">', $uri.'?charset=utf-8')."\n"; print sprintf('<frame name="bottom1" src="%s">', $uri.'?charset=euc-jp')."\n"; print '</frameset>'."\n"; } else { print "<body>"; mb_language('ja'); $sql = array(); array_push($sql , "SELECT '新',lower('新');"); array_push($sql , "SELECT '新品', substr('新品', 1, 1),substr('表', 1, 1);"); $dbh = array(); $user = $pass = ''; $dbh['3'] = new PDO('sqlite::memory:', $user, $pass); $dbh['2'] = new PDO('sqlite2::memory:', $user, $pass); print "charset[$charset]<br>\n"; function print_table($items ,$options=array()) { global $charset; print '<table border="1" cellpadding="5" cellspacing="0" bordercolor="#008000">'; print sprintf(' <tr> <td bgcolor="#F8FFE6">%s %s.x</td>' .'<td bgcolor="#F8FFE6">%s</td> </tr>' , mb_convert_encoding('表示結果', $charset, 'auto') , $options['ver'] , $charset ); foreach($items as $key => $value) { if (is_int($key)) { continue; } print "<tr>"; print '<td align="center" bgcolor="#CCFFCC">'.htmlspecialchars($key).'</td>'; print '<td align="center">'.htmlspecialchars($value).'</td>'; print "</tr>"; } print '</table>'; } foreach($dbh as $key => $value) { if (!$dbh[$key]) { $s = sprintf("sqlite[%s]に接続できませんでした。", $key); $s = mb_convert_encoding($s, $charset, 'auto'); print($s."<br>\n"); continue; } print ("<br>\n"); foreach ($sql as $sqlkey => $sqltext) { $sqltext = mb_convert_encoding($sqltext, $charset, 'auto'); print "[sql] ".htmlspecialchars($sqltext)."<br>\n"; foreach ($dbh[$key]->query($sqltext) as $row) { print_table($row ,array('ver'=>$key)); // print_r($row); } } $dbh[$key] = null; } } print "</body>"; ?> </html> |
標準関数上書き編 | |
substr pdoの例 |
mb_language('ja'); $charset = 'euc-jp'; // dbで使う文字コードを指定 function sqlite_ufunc_mb_substr($p1, $p2, $p3) { global $charset; $p2--; if (!$charset) { return mb_substr($p1, $p2, $p3); } return mb_substr($p1, $p2, $p3,$charset); } $db->sqliteCreateFunction('substr', 'sqlite_ufunc_mb_substr', 3); |
lower 2.xの例 |
sqlite_create_function ($db, 'lower', 'sqlite_ufunc_mb_lower'); function sqlite_ufunc_mb_lower($str) { global $charset; if (!$charset) { return mb_strtolower($str); } else { return mb_strtolower($str, $charset); } } |
sql関数との引数の違いを注意しながら mb_関数で 置換していくと そのまま使えるようになるかもしれないです。 注:利用する文字コードの指定を間違わないように適時変更してください。 |
|