メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL の文字列比較は、特に指定しない限り大文字と小文字を無視します。これは 一度人を驚かせ、後になって足をすくいます。そのため、何がそれを決めるのか、 1 つのクエリでどう変えるのかを知っておく価値があります。 始める前に mysql -u root -p sakila でクライアントを開いてください。

大文字と小文字の区別の仕組み

クエリの中の何もそれを決めません。決めるのは照合順序であり、すべてのテキスト列が 1 つ持っています。文字セットは列が保持できる文字を定め、その照合順序は文字を どう比較するかを定めます。1 つの比較に限って照合順序を上書きするには COLLATE を使います。
COLLATION_NAME を比較に使わせたい照合順序に、SEARCH_TEXT を一致させる値に 置き換えます。

例

  1. 大文字と小文字だけが異なる 2 つの文字列は等しい

  1. 列に対しても同じことが成り立つ

小文字の検索語が大文字のタイトルを見つけます。

  1. 列の照合順序を読む

照合順序の名前は末尾から読みます。ci は大文字と小文字を区別しない (case-insensitive) という意味で、例 2 が一致したのはそのためです。ai は アクセントを区別しない (accent-insensitive) という意味で、別の働きをします。 この照合順序では 'e' = 'é' は真ですが、utf8mb4_0900_as_cs では偽です。 この表は、自分の列の照合順序名の意味でもあります。上のクエリを任意のテーブルと列に 対して実行すると、どのルールの下で作業しているかが分かります。

  1. 大文字と小文字を区別する比較を求める

列に対しても同じように機能します。

列に対する COLLATE はインデックス検索を手放す

列のインデックスはその列自身の照合順序で作られているため、別の照合順序での 比較は、一致する値を見つけるのにそれを使えません。上のクエリに対する EXPLAIN は、検索ではなく 1,000 行すべてのスキャンを報告します。1,000 本の映画では何の コストもかかりませんが、大きなテーブルでは大きなコストになります。すべての クエリで大文字と小文字を区別する一致が必要な場合は、 文字セットと照合順序のガイドで、代わりに列をそのように 保存する方法を説明しています。

デフォルトはどこから来るのか

照合順序なしで作成されたデータベースはサーバーのものを、テーブルはデータベースの ものを、列はテーブルのものを引き継ぎます。したがって、その履歴のどこにも照合 順序が指定されていない列は、サーバーの設定のせいで大文字と小文字を区別せずに 比較しています。名前の前の @@ はサーバーの設定を読み、この 2 つはどれを 引き継いだかを教えてくれます。
サーバーは起動時の設定で答えるので、結果は MySQL についてではなく、自分の インストール環境についての事実として扱ってください。

識別子は別のルールに従う

列名は決して大文字と小文字を区別しません。データベース名とテーブル名は別の 問題で、lower_case_table_names が決めます。 SELECT @@lower_case_table_names; を実行すると、自分の状況が分かります。 セッションからは変更できません。SET GLOBAL lower_case_table_names=1 は ERROR 1238 (HY000): Variable 'lower_case_table_names' is a read only variable と答えます。これは起動時の設定で、サーバーが最初にどう設定されたかに結び付いて いるため、答えは今いるサーバーの性質として扱ってください。 実践的な助言は答えに依存しません。すべてのデータベース名とテーブル名を大文字か 小文字のどちらかに統一して書き、そのつづりをどこでも使ってください。そうすれば、同じ SQL を 2 つの サーバー間で移動しても、動いていたクエリが、存在しないテーブルのエラーである ERROR 1146 (42S02) になることはありません。

まとめ

  • 通常の照合順序は _ci で終わるため、文字列比較は大文字と小文字を無視すると考えてください。
  • 列の照合順序は INFORMATION_SCHEMA.COLUMNS から読みます。
  • 照合順序の名前は末尾から読みます。_ci と _ai は無視し、_cs、_as、および _bin は区別します。
  • 一度限りの大文字と小文字を区別する比較には COLLATE を使い、インデックス検索を手放すことを受け入れてください。
  • lower_case_table_names が何であれ、すべてのデータベース名とテーブル名のつづりを 1 つに保ちます。

関連項目