MySQLの照会順序
基本的に今は文字コードを全てUTF-8で統一するようにしている。もともとPHPはシフトJISが得意でないし、いまさらEUC-JPを使う理由もない。自分のウェブサイトを構築する場合は、携帯サイトを除いて出力もUTF-8だ(ウェブサービスとの親和性もいいし)。必然的にデータベースもUTF-8でデータを格納しているわけなんだが。
MySQLでいつも迷う点がある。いわゆる照会順序ってやつ。SQL serverなんかでは照合順序って名前になってることもある。照会順序とは「言語種別」と「ロケール」に基づく文字列の比較方法の規則のこと(らしい)。文字列の比較だからWHERE句での比較はもちろんだし、ORDER句の並び替えにも影響するので、希望通りの結果を得たい場合はしっかり設定しておかないといけない。でも、これ、いろいろあるんだな。
文字列に対しての影響を及ぼすわけだから、数値型カラムなどは関係ない。varchar型やtext型で設定しなくてはいけない(つまりカラムごとにも設定できるっぽい)。それにデータベースのデフォルト照会順序も設定できるし、テーブルでも照会順序を設定できる。照会順序で設定できる値は大量にあるのだが、日本語環境でUTF-8を使っている場合に設定するであろう値は以下の3つだ。
- utf8_bin
- utf8_general_ci
- utf8_unicode_ci
最初のはbin。これはバイナリ(binary)レベルで検査してくれる。バイナリで見てくれるわけだから、絶対確実。間違いなく期待通りの答えを返してくれそうな感じ。
あとの2つは両方とも後ろに_ciとなっているが、これは「case insensitive」の略。つまり大文字小文字(upper caseとlower case)を区別しない(「sensitive:敏感」でない)という意味だ。だからバイナリレベルでのチェックではないことは明らか。これだけ見ればbinがいいような気がするけれど、マルチバイトもシングルバイトも関係なくてバイトオーダーで検査するので、ひょっとしたら希望通りの動作にならないことがあるかもしれない。
で_ciな二つだが、前者(general)は英数の全角半角の判断くらいはしてくれるらしい(大文字小文字は判断しない)のに対して、後者(unicode)は全角半角大文字小文字も判断しないらしい。例えば文字列比較で以下のような例を考える。
- (半角大文字のA)=(全角大文字のA)
- (半角大文字のA)=(半角小文字のa)
前者(general)だと1はfalse、2はtrueだが、後者(unicode)だた1もtrue、2もtrueになる。どんな動きをしてほしいかということは、用途によってそれぞれだから一概にどちらが正しいとは言えないけれど、ちょっとややこしい。でも、前者のほうがなんとなく正確っぽいので、より厳密なのかなと思う。後者はなんとなくあいまいっぽいので、処理が簡単そう。だから正確度ならgeneral、速度ならunicodeということになるだろうか。
用途によるんだけど、まぁ、どれを使っても、一般人の考えているとおりの動作はしてくれなさそうだ。がんばって使い分けるしかない。