さすがに見逃せない話が多々あったので、ちと調べてみた。
で…大分見えてきた。ポイントは多分「3つの自動化」。
まずわかりやすいのは「文字コードの自動化」。
彼ら的には、EUCとしての「おはよう」とUTF-8としての「おはよう」を、つまり
euc('おはよう') = utf-8('おはよう')
を、trueにしたいわけだ。
まぁわからんでもない。面倒起こしやすいことも多々あるのだが。
次に。「スペースパディング」の自動化。
padding(パディング)はいいよね? ゼロパディングとかあるし。雑に書くと「データ量の不足分を一定の文字で埋める」の。
で。
charとvarcharの違い。charは固定長なのに対して、varcharは可変長。んじゃ可変部分をどうやってるかって言うと、大抵は「先頭の1バイトとか2バイトとか4バイトとか8バイトとか使ってそこにlengthを埋め込んでる」の。
翻って。charは固定長。んじゃ「char(10)に8文字いれて。のこり2文字どうする?」。
大抵の場合。ここを「スペースパディング」するざます。つまり「空白で埋める」。
だとすると。このタイミングにおいては
'01234567' = '01234567 '
がtrueにならないと困る。だってスペースは「システムがシステムの都合で勝手に入れたもの」だから。
で、この考え方を応用したんだか横着したんだかして、かくして
http://dev.mysql.com/doc/refman/5.1/ja/char.html
全てのMySQL照合は PADSPACE タイプの物だと覚えておいてください。これは、MySQLの中の全ての CHAR と VARCHAR 値が後続スペースを無視して比較されるという事を意味します。
って流れになる。
最後に。………これはどうしても想像しにくいんだけど。「lowerとupperの自動化」。
少なくとも彼らの感性において、
'a' = 'A'
というのは、trueらしい。ちなみにこの延長線として、割合に容易に
'a' = 'A' = euc('A') = utf-8('a')
がtrueになるんだろうと思われる。後ろ二つはいわゆる「多バイト文字」ね。
そう考えた根拠はここ。
http://dev.mysql.com/doc/refman/5.1/ja/charset-binary-op.html
キャラクタ毎よりも、バイト毎の比較を強制的に行う簡単な方法です。
上述、キャラクタ的には同一視してると思われる。
さて。「文字コードの自動化」は、人によりけり微妙だけど、俺的にはNG。パディングと大小文字の自動化は論外。
で…対策は人生色々女も色々。
とりあえず文字コード抑制として、コンパイルオプション&my.cnfに手を入れてみる。
具体的には以下参照。
http://vivian.reverb.jp/mysql4.1.html
# MySQL4.1.12 ソースから--with-charset=binaryの指定ありでコンパイル(こうするとクライアントをbinaryで作れる)。
# my.cnfは以下。[mysqld]
default-character-set=utf8
[mysqldump]
default-character-set=binary
これで、おそらくは「文字コードの自動化」が抑止できる。
以下、確認用のメモ。
mysql> SHOW VARIABLES LIKE "char%"; character_set_client クライアントから渡されるSQL文のキャラクタセット character_set_connection SQL文中の文字列リテラルのキャラクタセットのデフォルト値 character_set_database CREATE DATABASE でキャラクタセットを指定しなかった場合にこの値が使用される character_set_results クライアントへ結果を返す時のキャラクタセット character_set_server character_set_database のデフォルト値に影響する character_set_system テーブル名やカラム名用。どうあがいてもutf8で固定
大文字小文字については、create tableのchar、varchar、textにbinaryをつけるのがひとつ。
で、大小文字+スペースパディングの抑止には、binaryによるキャストが有効。
ただ
http://mysql.mirrors-r-us.net/doc/refman/4.1/ja/case-sensitivity-operators.html
注意: MySQL の一部のコンテキストでは、インデックス付きのカラムを BINARY にキャストすると、インデックスを効率的に使用できなくなる。
という予想通りの文句があるので、binaryキャストは定数(シングルクォートした文字列)に対してやるほうが安全。
書式的には
カラム名 = binary '定数' カラム名 = binary('定数')
こんな感じ。
で、最後に、すばらしくはしたないアイデア(笑
http://dev.mysql.com/doc/refman/5.1/ja/binary-varbinary.html
BINARY と VARBINARY タイプは、非バイナリ文字列ではなく、バイナリ文字列を含んでいるところ以外で CHAR と VARCHAR に似ています。それは、それらが文字の文字列ではなく、バイトの文字列を含んでいるという事です。これは、それらが文字セットを持たず、ソートと比較は値の中の数値バイトに基づいているという意味です。
http://dev.mysql.com/doc/refman/5.1/ja/blob.html
BLOB カラムはバイナリ文字列(バイト文字列)として扱われます。TEXT カラムは非バイナリ文字列(文字の文字列)として扱われます。BLOB カラムは文字セットを持たないので、ソートと比較は値の中の数値バイトに基づいています。TEXT カラムは文字セットを持つので、値は文字セットの照合に基づいてソート、比較されます。
つまりね。
sed -e s/varchar/varbinary/ sed -e s/text/blob/
ほぉらはしたないw
とりあえず……………おぢちゃん疲れたよ orz