MySQLとPostgresの両方で大文字と小文字を区別しないクエリをどのように記述しますか?
-
03-07-2019 - |
質問
開発用にMySQLデータベースをローカルで実行していますが、Postgresを使用するHerokuにデプロイしています。 Herokuはほとんどすべてを処理しますが、大文字と小文字を区別しないLikeステートメントは大文字と小文字を区別します。 iLikeステートメントを使用できますが、ローカルMySQLデータベースはそれを処理できません。
MySQLとPostgresの両方と互換性がある、大文字と小文字を区別しないクエリを記述する最良の方法は何ですか?または、アプリが通信しているデータベースに応じて、LikeステートメントとiLikeステートメントを別々に記述する必要がありますか?
解決
select * from foo where upper(bar) = upper(?);
呼び出し元でパラメーターを大文字に設定すると、2番目の関数呼び出しを回避できます。
他のヒント
この話の教訓は、開発と生産に異なるソフトウェアスタックを使用しないことです。決して。
最終的にはdevで再現できないバグが発生します。あなたのテストは価値がないでしょう。しないでください。
別のデータベースエンジンを使用することは問題外です-LIKE以外の動作をする場合がはるかに多くあります(また、データベースで使用されている照合を確認しましたか?すべてのケースで同じですか? 、同じように機能するvarchar列のORDER BYを忘れることがあります)
Arelを使用:
Author.where(Author.arel_table[:name].matches("%foo%"))
matches
は、Postgresには ILIKE
演算子を使用し、その他のすべてには LIKE
を使用します。
postgresでは、これを行うことができます:
SELECT whatever FROM mytable WHERE something ILIKE 'match this';
MySQLに相当するものがあるかどうかはわかりませんが、これはいつでもできますが、少しugいですが、MySQLとpostgresの両方で動作するはずです:
SELECT whatever FROM mytable WHERE UPPER(something) = UPPER('match this');
いくつかの答えがありますが、どれも非常に満足のいくものではありません。
- LOWER(bar)= LOWER(?)は、MySQLとPostgresでは動作しますが、MySQLではひどく動作する可能性が高い:MySQL LOWER関数のため、インデックスを使用しません。 Postgresでは( LOWER(bar)で)機能インデックスを追加できますが、MySQLはこれをサポートしていません。
- MySQLは(大文字と小文字を区別する照合を設定していない限り)大文字と小文字を区別しないマッチングを自動的に行い、そのインデックスを使用します。 ( bar =?)。
- データベース外のコードから、 bar および bar_lower フィールドを維持します。ここで、bar_lowerには lower(bar)の結果が含まれます。 (これは、データベーストリガーを使用しても可能です)。 (このソリューションの説明は、 Drupal をご覧ください)。これは不器用ですが、少なくともほとんどすべてのデータベースで同じように実行されます。
REGEXPは大文字と小文字を区別せず(BINARYと併用しない限り)、次のように使用できます...
SELECT id FROM person WHERE name REGEXP 'john';
...「John」、「JOHN」、「john」などに一致する
PostgreSQL 8.4を使用している場合、 citext モジュールを使用できます。大文字と小文字を区別しないテキストフィールドを作成します。
searchlogic プラグインをチェックアウトすることも検討してください。これは LIKE / ILIKE スイッチ。
ブロック内のサブストリングを一致させたい場合は、postgresで〜*を使用することもできます。 〜は大文字と小文字を区別する部分文字列、〜*は大文字と小文字を区別しない部分文字列に一致します。操作は遅いですが、検索に役立つかもしれません。
Select * from table where column ~* 'UnEvEn TeXt';
Select * from table where column ~ 'Uneven text';
「Some Uneven text here」で両方がヒットします; 前者だけが「ここのUNEVEN TEXTの一部」にヒットします
上位に変換することは、最もよく使用される3つのRailsデータベースバックエンドの互換性のある構文をカバーするため、最適です。 PostgreSQL、MySQL、SQLiteはすべてこの構文をサポートしています。アプリケーションまたは条件文字列で検索文字列を大文字にする必要があるという(わずかな)欠点があり、少し見栄えが悪くなりますが、互換性を得ると価値があると思います。
MySQLとSQLite3の両方に、大文字と小文字を区別しないLIKE演算子があります。大文字と小文字を区別するLIKE演算子と、大文字と小文字を区別しない検索用のPostgreSQL固有の(マニュアルによる)ILIKE演算子を持っているのは、PostgreSQLだけです。 Railsアプリケーションの条件では、LIKEの内側にILIKEを指定できますが、アプリケーションはMySQLまたはSQLiteで動作しなくなることに注意してください。
3番目のオプションは、使用しているデータベースエンジンを確認し、それに応じて検索文字列を変更することです。これは、ActiveRecordの接続アダプターにハッキング/モンキーパッチを適用し、PostgreSQLアダプターにクエリ文字列を変更して" LIKE"を置換させることで、より適切に実行できる場合があります。 " ILIKE"クエリの実行前。ただし、このソリューションは最も複雑であり、両方の用語を大文字にするなどの簡単な方法に照らして、これは努力に値するとは思いません(ただし、この方法で多くのブラウニーポイントを獲得できます)。