web-dev-qa-db-ja.com

MySQLがUTF-8で「大文字と小文字を区別しない」と「アクセントを区別しない」を機能させる方法

「utf8-UTF-8 Unicode」のスキーマを文字セットとして持ち、「utf8_spanish_ci」の照合順序を持っています。

内部テーブルはすべて、前述のように同じ文字セットと照合順序を持つInnoDBです。

ここに問題があります:

のようなクエリで

SELECT *
FROM people p
WHERE p.NAME LIKE '%jose%';

83の結果行が表示されます。私はそれを知っているので、84の結果が得られるはずです。

変更する場所:

WHERE p.NAME LIKE '%JOSE%';

まったく同じ83行を取得します。 JoSe、Jose、JOSeなどの組み合わせ。すべて同じ83行が報告されます。

問題は、アクセントがゲームで遊ぶときに発生します。もしそうなら:

WHERE p.NAME LIKE '%josé%';

結果はありません。 0行。

しかし、私がするなら:

WHERE p.NAME LIKE '%JOSÉ%';

結果の行は1つだけなので、1行になります。これは、「ホセ」をアクセントにして大文字にした唯一の行です。

アクセント付きの文字が大文字のままであるかどうかに関係なく、josÉ、JoSÉ、または私が行う任意の組み合わせを試してみましたが、実際にはデータベースに格納されていて、唯一の行を返します。 JOSEで大文字を使用してどのような組み合わせで「É」を「é」に突然変更しても、行が返されません。

したがって結論:

  • ゲームでラテン文字がプレイされない場合、大文字と小文字は区別されません。
  • ラテン文字が表示される場合は、大文字と小文字が区別されます。
  • JOSEまたはjoseを検索する場合と同様に、アクセント記号が区別されます。必要な84行ではなく、83行しか取得されません。

私が欲しいものは?

  • 「jose」、「JOSE」、「José」、「JOSÉ」、「JÒSE」、「jöse」、「JoSÈ」などを検索するには、存在することがわかっている84行を返す必要があります。検索で大文字と小文字を区別せず、「ラテン語」を区別しないようにします。

COLLATIONLIKEのようなソリューションは私には機能しません。理由はわかりません...

私に何ができる?

前もって感謝します!

編集:

私が何かをするなら:

WHERE p.NAME LIKE '%jose%' COLLATE utf8_general_ci;

エラーが発生します:

COLLATION 'utf8_general_ci'は、CHARACTER SET 'latin1'では無効です

また、列で可能なすべての照合順序も変更しました。

そして、私が次のようなことをした場合:

WHERE p.NAME LIKE _utf8 '%jose%' COLLATE utf8_general_ci;

同じ83行がレポートされ、まるで何もしなかったかのように...

21
Lightworker

検索と順序付けにアクセントを区別しない照合を使用しようとしました。

http://dev.mysql.com/doc/refman/5.0/en/charset-collat​​ion-implementations.html

実は、NAME列は、latin1(8ビット)文字セットに格納されているようです。そのため、mySQLは次のように不平を言っています。

  COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1'

試してみると思い通りの結果が得られるかもしれません

 WHERE CONVERT(p.NAME USING utf8) LIKE _utf8 '%jose%' COLLATE utf8_general_ci;

しかし、注意してください!

WHEREステートメントの列で任意の種類の関数(この例ではCONVERT)を使用すると、インデックスを使用した検索を最適化するMySQLの試みが無効になります。このプロジェクトが大きくなる場合(つまり、テーブルに多数の行が含まれる場合)、データをlatin1ではなくutf8形式で保存する必要があります。 (おそらくあなたはすでにあなたのLIKE '%whatever%'検索語もMySQLのインデックス作成を無効にします。)

11
O. Jones

他の誰かがこの問題に遭遇した場合に備えて、少なくとも私にとっては、問題を解決する方法を見つけました。

PHPを使用して、データベースからレコードを挿入および取得しています。私のデータベースでも、テーブルと列はutf8であり、PHPファイル、真実はPHPとMySQLの間の接続で使用されるエンコーディングがlatin1を使用して作成されているということです。私はこれを使用してこれを見つけることができました

$mysqli->character_set_name();

どこ $mysqliはオブジェクトです。

検索が期待どおりに機能し始め、アクセントのある文字またはアクセントのない文字の大文字と小文字を区別しないレコードを返すには、接続の文字セットを明示的に設定する必要があります。

これを行うには、以下を実行する必要があります。

$mysqli->set_charset('utf8');

$ mysqliはmysqliオブジェクトです。データベース機能をラップするデータベース管理クラスがある場合、これは完全なアプリに簡単に適用できます。そうでない場合は、接続を開くすべての場所でこれを明示的に設定する必要があります。

私はすでにこれについておかしくなっていたので、これが誰かを助けてくれることを願っています!