AWS / PHP / Python ちょいメモ

amazon web service , PHP, Python を使ったときのメモ。日本語でググってもわからなかった事を中心に。

Django と SQLite/MySQL : 照合順序を意識しよう

Django は、pythonのWebアプリケーションフレームワークで、MVCならぬMTV (Model - Template - View) モデルで構成されています。

Model を定義することで、バックエンドのデーターベース定義などは自動で生成してくれる形となっており、プログラミングする事に注意を払う事ができるのが良いところ。(僕の解釈が間違ってなければ)見えないところでは、O/Rマッパーが働いてて、DBにアクセスしたりしてくれています。

ただ完全に隠蔽できてるかというと、そうじゃないからたまには意識せねばというTIPSです。

結論からいうと、DBMSによってデフォルトの照合順序違うよ。ってダケです。

SQLiteの場合

手軽に使えるDBのSQLite。手軽なんで何も考えずに使ってましたが、照合順序のデフォルトは BIN:binary です。バイナリだから、日本語でも何でも放り込めるって言う事ですね。

Datatypes In SQLite Version 3

6.1 Assigning Collating Sequences from SQL
Every column of every table has an associated collating function. If no collating function is explicitly defined, then the collating function defaults to BINARY.

6.1 割り当てられる照合順序
各テーブルの各カラムは、関連した照合する機能を持ちます。もし、明示的に照合機能が指定されない場合は、バイナリがデフォルト照合機能となります。

何も考えずにDjangoSQLiteをバックエンドに指定していると、照合順序がバイナリである事を頭の片隅においておく必要があります(DBを入れ替えると、こういう影響に気づく。詳細は、後日書く予定)。

ちなみに3つの組み込み照合方法があるようです。どれも BINARY とほぼ同じ感じですね。別途、追加で登録する事も可能とか。

6.0 Collating Sequences
...SQLite has three built-in collating functions: BINARY, NOCASE, and RTRIM.

MySQLの場合

対して、しっかり考えて使おうMySQL側ですが、デフォルトが何になるかはインストール方法などで異なるかと思います。

d.hatena.ne.jp


僕の場合SQL Serverを過去に使っていたので utf8_general_ci あたりを設定したりしていました。しかし、SQLiteからの移行を行うと、もともとBINだったものなので、ソート順が異なるなどの弊害がでてしまいました。

SQL文を直接記述する場合には、クエリ単位で照合順序を明示するなどの対策も打てると思いますが、Djangoフレームワークの上では難しいだろうと思われます。そこで、BINでのソートが必要なカラムだけを、個別に変更する事にしました。

もちろんDjangoの仕組みではサポートされない(と思われる)ので、ただのシェルスクリプトを用意しての対応です。

alter table contents
 modify `key` varchar(255) CHARACTER SET ascii NOT NULL
 collate ascii_bin;

設定したら、次のコマンドで確認。

show create table contents\G

以上、Webアプリケーションフレームワーク使っているからといって、DBをただの箱として使っちゃいけないねというメモでした。