(MySQL, SQLite3)大文字小文字を区別する・しない方法いろいろ
目次
- 原則
- MySQL: 大文字小文字を区別させる
- SQLite3: 『=』で大文字小文字を区別させない
- MySQL, SQLite3: 『LIKE』で区別させない
- MySQL, SQLite3: 重複データを探したい
原則
下記のような、大文字小文字の種類だけが異なるデータがあるとします。HOGE Hoge hoge下記のSQLを実行すると、大文字小文字は区別されるのでしょうか?
結果はご覧の通り。
SELECT * FROM posts WHERE name = 'hoge'
SELECT * FROM posts WHERE name LIKE 'hoge'
MySQL | SQLite3 | |
---|---|---|
= | 区別しない | 区別する |
LIKE | 区別しない | 区別しない |
MySQL: 大文字小文字を区別させる
MySQLは特に指定がなければ大文字小文字は区別しません。では、区別させるには?
テーブル作成時に、フィールドにBINARY属性を加える
これは恒久的な設定です。phpMyAdminで変更する場合
SQLで変更する場合
テーブル作成時途中で
CREATE TABLE `posts` (
`id` INT(11) PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(100) BINARY,
...
);
ALTER TABLE `posts` MODIFY `name` VARCHAR(100) BINARY;
検索時に、フィールドにBINARY演算子を加える
これは一時的な設定です。SELECT * FROM `posts` WHERE `name` = BINARY 'hoge';
SQLite3: 『=』で大文字小文字を区別させない
SQLite3の=
は大文字小文字を区別します。では、区別させないようにするには?
テーブル作成時に、COLLATE句で『nocase』を指定する
これは恒久的な設定です。※SQLite2ではCOLLATE句は使えません。
CREATE TABLE "posts" (
"id" INTEGER PRIMARY KEY AUTO_INCREMENT,
"name" CHAR COLLATE nocase,
...
);
検索時に、COLLATE句で"nocase"を指定する
これは一時的な設定です。SELECT * FROM "posts" WHERE "name" COLLATE nocase = 'hoge';
MySQL, SQLite3: "LIKE"で区別させない
MySQLでもSQLite3でも、LIKE
演算子を使うと大文字小文字は区別されません。つまり、下記のSQLでは
HOGE
,Hoge
,hoge
の全てにヒットしてしまいます。あいまい検索のために"LIKE"を使いたいが、大文字小文字を区別してほしい。
SELECT name FROM posts WHERE name LIKE 'ho%'
MySQLならば可能ですが、今のところ、SQLite3では解決法を見つけられませんでした。
CREATE時に
COLLATE nocase
を指定してもダメですorz
(MySQL)区別される
SELECT * FROM `posts` WHERE `name` LIKE BINARY 'ho%';(SQLite3)区別されない
SELECT * FROM "posts" WHERE "name" COLLATE BINARY LIKE 'ho%';
MySQL, SQLite3: 重複データを探したい
で、ここからが本題です。重複データを探したい場合。
MySQL, SQLite3共通のSQLは下記。
しかし、これは大文字小文字が区別されてしまいます。
大文字小文字が区別される
SELECT name, COUNT(name) FROM posts GROUP BY name HAVING COUNT(name) > 1;
HOGE
,Hoge
,hoge
を"重複している!"と見做したい場合は下記のように。
大文字小文字を区別しない
(MySQL)
SELECT `name`, COUNT(`name`) FROM `posts` GROUP BY `name` COLLATE utf8_unicode_ci HAVING COUNT(`name`) > 1;(SQLite3)
SELECT "name", COUNT("name") FROM "posts" GROUP BY "name" COLLATE nocase HAVING COUNT("name") > 1;
これを何に応用するのかというと…、Twitterハッシュタグのデータベースの整理です。
先日、さくらサーバからロリポップへ引越ししたのですが、その際にデータベースもMySQLからSQLite3へ変更しました。
で、MySQLの時は、ハッシュタグを新規登録する際に大文字小文字を区別せずに重複がないかを確認する処理が正しく動作していたのですが、SQLite3ではそれがうまくいかず、重複タグが多数生まれてしまいました。
それを検出して削除・統合するために、上記のSQLが必要になるわけです。
…あー…、めんどくさい…orz
でも、とても勉強になりました。
なお、CakePHPのfind
メソッド各種の大文字小文字の区別の違いについては下記をご覧ください。
- ブログ内記事: 【CakePHP】DB検索の際の大文字小文字の区別のまとめ