MySQL+PHPで日本語検索(SELECT文)ができません。



現在MySQLとPHPを使った(フレームワークとしてcakephpを使用しています)ウェブシステムの構築をしてます。

そこで、テストサーバ(XREAのphp5サーバです)でうまくいったものを本サーバー(さくらの専用サーバーFreeBSD使用)にアップしたところ、日本語のSELECT文に反応しなくなってしまいました。

SQL文はこちらです。
SELECT `Hoge`.`prefecture` FROM `hoges` AS `Hoge` WHERE prefecture="北海道"

日本語以外のパラメータでSELECT文を入れてみたら正常に動作しました(例えばid=5など)。
文字コードはサーバ・MySQLではUTF8を使用しており、クライアントは携帯対応を考えているためSJISにしてます。
テストサーバは
SET NAMES SJIS
を入れることで問題なく進んだんですが、
本サーバでは、SET NAMES SJISでもUTF8でも駄目でした。

また、
mb_convert_encodingを使ってSJISとUTF8で同じ文字を同時に検索させてみたんですがそちらも駄目でした。

なお、本サーバをいじる権限がないので、プログラムだけで対応できる施策を探しています。
以下、テストサーバと本サーバーのMySQLです。
テストサーバー(XREA+)
MySQL: 5.1.22-rc
本サーバ
MySQL: 5.0.45

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2007/12/14 01:20:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:ffmpeg No.1

回答回数1202ベストアンサー獲得回数9

ポイント27pt

mysql_query('set character set sjis');

id:lemolemo75

回答ありがとうございます!

SET NAMES SJISを消してset character set sjisを入れてみたんですが、駄目でした。

また、両方同時に入れても同様でした。

これってMySQLのバージョンのせいなんでしょうか?

2007/12/07 03:51:23
id:bayan No.2

回答回数100ベストアンサー獲得回数13

ポイント27pt

SELECT文に反応しない状況は、結果の件数が 0 件なのか、

それともSQLの実行がエラーになっていたりするのか気になりました。

$rs = mysql_query($sql);

if($rs){

echo mysql_num_rows($rs) . "件";

}else{

echo "Error";

}

はずしているかもしれませんが、試しに文字列を囲むのに " ではなく ' を使ってみるとどうでしょうか。

SELECT `Hoge`.`prefecture` FROM `hoges` AS `Hoge` WHERE prefecture='北海道'

MySQLサーバがANSIモードで動作していると、

文字列の引用に二重引用符を使用することはできない。二重引用符を使用すると、識別子として解釈されてしまうためである。

ということがあるみたいです。

詳しくは、

http://dev.mysql.com/doc/refman/4.1/ja/ansi-mode.html

http://dev.mysql.com/doc/refman/5.1/ja/server-sql-mode.html

先に

SET sql_mode = '';

を実行すれば " でも通りそうですが未確認です。。。


あと文字コードがらみですが、 で、

mbstring.xxx (mbstring.internal_encoding 等) がどうなっているか、両方のサーバの設定をくらべて見るとどうでしょうか。

すでになさっていたらごめんなさい。

id:lemolemo75

回答ありがとうございます!

説明不足すいません。SELECT文に反応しないというのは、結果が0件ということです。エラーは出ません。

シングルクオートにしてみたんですが、結果は同じでした。

phpinfo();で調べてみました。

本サーバ

mbstring.detect_order no value no value

mbstring.encoding_translation On On

mbstring.func_overload 0 0

mbstring.http_input pass pass

mbstring.http_output pass pass

mbstring.internal_encoding EUC-JP EUC-JP

mbstring.language Japanese Japanese

mbstring.strict_detection Off Off

mbstring.substitute_character no value no value

テストサーバ

mbstring.detect_order auto auto

mbstring.encoding_translation Off Off

mbstring.func_overload 0 0

mbstring.http_input auto auto

mbstring.http_output pass pass

mbstring.internal_encoding UTF-8 UTF-8

mbstring.language Japanese Japanese

mbstring.strict_detection Off Off

mbstring.substitute_character no value no value

これって、つまりPHPの問題なんでしょうか?学が浅く申し訳ありません。

2007/12/07 14:06:45
id:KeyKey No.3

回答回数29ベストアンサー獲得回数4

ポイント26pt

テスト環境ではうまくいき、なお且つ日本語以外のSELECTはうまく結果が返ってくることから

やっぱり原因は文字コードだと考えるべきだと思います。

何も間違っているのはSELECT文の文字コードだけとは限りません。


一度以下のSELECTで全部出力してみて日本語の部分がきちんとUTF8で返ってくるのか確認してみてはどうでしょうか?

SELECT `Hoge`.`prefecture` FROM `hoges` AS `Hoge`;

もしかしたらMySQLがUTF8なのにEUC-JPなどでINSERTされていて復元不可能な文字化けを起こしているかもしれません。

SELECT時の文字コードが怪しいということはINSERT時の文字コードも疑ってかかったほうがいいと思います。

  • id:bayan
    うぁぁ、はずしていましたね。。。
    あと <? phpinfo(); > と書いたら消えてますね。
    でも意図が伝わってよかったです♪

    以下ちょっと自信がないのですが、ブラウザから送信されるデータは、
    HTMLのヘッダの Content-Type に charset=Shift_JIS と書かれていれば
    SJISで送信されていると思います。

    テストサーバは、

    <blockquote>
    mbstring.encoding_translation Off
    </blockquote>

    なので、ブラウザから送信されたデータの文字コードを自動変換しません。
    だから変数の文字コードは SJIS のままでしょう。

    で、SET NAMES SJIS をしているので、MySQLに渡すデータは
    SJIS であるいう前提で MySQLデータベースの文字コードである
    UTF-8 へ変換され、検索に成功していると思います。

    ※次のURLによると set character set sjis は検索結果の
    文字コードを SJIS にしろという指示になるようですね。
    http://dev.mysql.com/doc/refman/4.1/ja/charset-connection.html

    一方、本番サーバは、
    <blockquote>
    mbstring.encoding_translation が On で、
    mbstring.internal_encoding EUC-JP
    </blockquote>

    なので、ブラウザから送信されたデータは EUC-JP に自動的に変換されます。
    変数のデータが EUC-JP になっているのに、SJIS とみなとして UTF-8 に
    変換されているから、おかしなデータになり検索がヒットしない考えられます。


    さて対策はどうしましょうか。
    本番サーバの設定 (php.ini や httpd.conf) がないのですよね。。。

    mbstring.encoding_translation はプログラムでは変更できません。

    mbstring.internal_encoding は、
    <blockquote>
    ini_set("mbstring.internal_encoding","SJIS");
    </blockquote>

    のようにして変更できるようですので、試してみてはどうでしょうか。

    http://www.php.net/manual/ja/ini.php
  • id:lemolemo75
    >>bayanさん

    何度もありがとうございます。

    ini_set("mbstring.internal_encoding","SJIS");

    を試してみたんですが、駄目でした。(これってプログラムの最初に埋め込めば良いんですよね??)

    検索システムですが、ブラウザからデータを送信するのではなく、ブラウザからは数字をGETで送ってもらってそれにあわせてサーバー側のプログラムでSQL文を作って送るという形にしてます。

    エンコードされてる可能性がある場所がもう出尽くしてしまった感じがするんですが。。

    他に変えられる場所ってあるんでしょうか?
  • id:bayan
    すみません、ずいぶん経ってしまいました。
    もう解決されてしまっているかもしれませんね。

    だめでしたか。。。
    ブラウザが送信した文字データを使うのではなく、サーバー側で
    SQL文を作っているとすれば、PHPによる自動変換は関係ないですね。
    それにから確認したところ mbstring.http_input pass であれば、
    自動変換は行われませんね。

    本番サーバーにアップするPHPスクリプトはSJISで書かれているでしょうか。

    一度組み立てたSQLをブラウザに出力してみると、文字コードは何になっているか確認してみるとどうでしょうか。

    可能であれば本番サーバーにssh等でログインして、 mysql コマンドから実行して見たいところです。
  • id:lemolemo75
    すいません。紆余曲折を経て、解決しました!と言いたいところなんですが、実は解決していません。

    >本番サーバーにssh等でログインして、 mysql コマンドから実行

    これやってみたんですが、(と言っても本番と同じ環境のstagingサーバーなんですが)文字コードはUTF8で出てきていました。

    また、stageサーバーの方で、sjisでデータベースを構築したんですが、それでも駄目でした。

    一体何が原因なのか、全くわからず悩んでいます。

    困りました。一体何が原因なのでしょうか?
  • id:devichan
    参考
    http://www.ironhearts.com/diary/archives/000868.html
  • id:devichan
    MySQLでは、原則「"」でなく「`」(バッククォート)だそうです。
    MySQLを非ANSIで使った場合、「"」=「'」(アポストロフィー):文字定数

    「`」と「'」混じってませんか?

  • id:adachi_c
    ・サーバ側テーブル名の「北海道」はutf8になっているのか?
    ・sqlに書かれた「北海道」はutf8になっているのか?
    この2つはもういちど確認したほうがいいと思います。たぶん一致していません。


    テーブルcreate時に文字コードを指定するのが確実でしょう。

    CREATE TABLE `北海道` (
    `id` int(11) NOT NULL auto_increment,
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    sakuraを使ってるのであれば、mysqladminから、
    文字コードが本当にutf8になっているかどうか確かめることができます。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません