|
Sidebar
|
SQLite Tips(sjis)
作成:2006.0915
編集:2006.09.15
【SQL】 |
文字化け |
|
【現象】
shift-jisやeucで
データに標準関数を使用すると
予期せぬ
文字化けを誘発します。
【対応】 |
◎ |
マルチバイトに対応したユーザー関数を組み込む |
○ |
utf8でデータ扱う |
|
例 |
SELECT '新',lower('新');
表示結果 2.x, 3.x |
sjis |
euc |
utf8 |
'新' |
新 |
新 |
新 |
lower('新') |
迅 |
新 |
新 |
|
例 |
SELECT '新品', substr('新品', 1, 1),substr('表', 1, 1);
表示結果 2.x |
sjis |
euc |
utf8 |
'新品' |
新品 |
新品 |
新品 |
substr('新品', 1, 1) |
- |
? |
? |
substr('表', 1, 1) |
- |
? |
? |
表示結果 3.x |
sjis |
euc |
utf8 |
'新品' |
新品 |
新品 |
新品 |
substr('新品', 1, 1) |
- |
? |
新 |
substr('表', 1, 1) |
\ |
表 |
表 |
注) - ? は表示不能 |
例 |
SELECT like('_\','表'), '表' like '_\'
表示結果 2.x |
sjis |
euc |
utf8 |
like('_\','表') |
1 |
0 |
0 |
'表' like '_\' |
1 |
0 |
0 |
表示結果 3.x |
sjis |
euc |
utf8 |
like('_\','表') |
1 |
0 |
0 |
'表' like '_\' |
1 |
0 |
0 |
|
まとめ |
2.x |
上の例からもわかるように
文字列関係の標準関数を利用すると
意図しない結果が返ります。
文字列関係の標準関数を使わず、
ユーザー定義関数を使いましょう
※ユーザー関数で 標準関数を上書きすることができます。 |
注意キーワード例:
like, substr, lower, ........ |
3.x |
文字操作系の標準関数を使う場合は
utf8でデータを扱いましょう |
|
※ユーザー関数で 標準関数を上書きすることができます。 |
・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_関数で 置換していくと
そのまま使えるようになるかもしれないです。
注:利用する文字コードの指定を間違わないように適時変更してください。 |
|
|
|
Sidebar
|