Rails の database.yml で collation を指定する

定期的に引っかかるので備忘録として。検証には Rails 4.0.8 及び Mysql 5.6.10 を使用しました。

Rails から MySQL を使う際、何も考えずにデフォルトのまま設定していくと、大体の場合小文字 a と大文字 A が区別されないデータベースが作成されます。具体的にサンプルを示すと

SELECT 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
|         1 |
+-----------+

このように 'a' = 'A' が真となってしまいます。主にメールアドレスなどの一貫性を保証したい時に問題になります。

こうした問題を解消するために使われるのが collation の指定です。バージョン 5.1 の記事ですが、公式ドキュメントはこちら。

http://dev.mysql.com/doc/refman/5.1/ja/charset-unicode-sets.html

詳しい解説は省きますが、今回は utf8_bin を collation に指定できれば問題が解決します。

新規作成する場合

config/database.yml に記述を追加します。

development:
  adapter: mysql2
  encoding: utf8
  collation: utf8_bin
  reconnect: false
  database: some_project_dev
  username: username
  password: password
  host: localhost

後は普段のように rake db:create からスタートすれば問題ありません。

既存のテーブルを何とかする場合

既存のデータベースについて設定を変更するには MySQL のクエリを直接発行する必要があります。

ALTER DATABASE dbname DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

しかし、この設定が適用されるのは上記クエリの受付後に作られたテーブル等のみで、既存のデータについてはどうしても区別ができないようです。そのような場合、明示的に BINARY オペレータを用いる事で比較を行います。

SELECT BINARY 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
|         0 |
+-----------+

ただし、この方法はパフォーマンス的にあまりオススメされないらしいので、必要なのであれば極力最初から大文字小文字(あるいはその他の何か)が区別可能なデータベースを作成するようにした方がいいでしょう。