この記事は公開されてから8年経過しています。現在とは内容が異なる場合がありますのでご注意ください。
最新の記事や関連記事をお探しの方は下の「サイト内検索」で検索してみてください。
最新の記事や関連記事をお探しの方は下の「サイト内検索」で検索してみてください。
結論からさきに書くと文字列型のカラムに 0 という文字の入ったレコードを検索するときは文字列として検索しましょう
ってお話。
VARCHAR なカラムに 数字 又は 空文字、NULL のいずれかが入った次のようなテーブルがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
mysql> CREATE TABLE IF NOT EXISTS `test` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `point` VARCHAR(16) NULL DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARACTER SET utf8; mysql> INSERT INTO `test` VALUES (null, null), (null, 10), (null, 0), (null, 5) ,(null, 3), (null, 0), (null, 1), (null, '') ,(null, 4), (null, 2), (null, 1), (null, 1) ; mysql> SELECT * FROM `test`; +----+-------+ | id | point | +----+-------+ | 1 | NULL | | 2 | 10 | | 3 | 0 | | 4 | 5 | | 5 | 3 | | 6 | 0 | | 7 | 1 | | 8 | | | 9 | 4 | | 10 | 2 | | 11 | 1 | | 12 | 1 | +----+-------+ 12 rows in set (0.00 sec) |
ここで point が 0 の件数だけを取得したくて次のような SELECT を実行します。
1 2 3 4 5 6 7 |
mysql> SELECT COUNT(`id`) FROM `test` WHERE `point` = 0; +-------------+ | COUNT(`id`) | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec) |
あれ?何故か 2 じゃなくて 3 となってしまいました。
なぜでしょうか?COUNT じゃなくてレコードを表示してみましょう。
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM `test` WHERE `point` = 0; +----+-------+ | id | point | +----+-------+ | 3 | 0 | | 6 | 0 | | 8 | | +----+-------+ 3 rows in set (0.00 sec) |
おや? point カラムが空文字になっているレコードもマッチしてしまいました。
代わりに次のような SELECT だとどうでしょうか。
1 2 3 4 5 6 7 8 |
mysql> SELECT * FROM `test` WHERE `point` = '0'; +----+-------+ | id | point | +----+-------+ | 3 | 0 | | 6 | 0 | +----+-------+ 2 rows in set (0.00 sec) |
お、正しく point カラムに 0 と記録されているレコードだけになりました。
COUNT の場合も問題ないです。
1 2 3 4 5 6 7 |
mysql> SELECT COUNT(`id`) FROM `test` WHERE `point` = '0'; +-------------+ | COUNT(`id`) | +-------------+ | 2 | +-------------+ 1 row in set (0.00 sec) |
文字列型のカラムに空文字が入っている場合に WHERE でエスケープせずに「数字の0」とした場合は、空文字にもマッチするようです。
ちなみにこれが 0 じゃない場合は問題ないみたいです。
1 2 3 4 5 6 7 |
mysql> SELECT COUNT(`id`) FROM `test` WHERE `point` = 1; +-------------+ | COUNT(`id`) | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec) |
というか対象のカラムが文字列型ならちゃんとエスケープした値で検索しろってことですよね。
※参考までに
空文字だけで検索するときちんと空文字のレコードだけになりますし、NULL の場合も IS NULL を使えば NULL のレコードだけになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
mysql> SELECT COUNT(`id`) FROM `test` WHERE `point` = ''; +-------------+ | COUNT(`id`) | +-------------+ | 1 | +-------------+ 1 row in set (0.00 sec) mysql> SELECT COUNT(`id`) FROM `test` WHERE `point` IS NULL; +-------------+ | COUNT(`id`) | +-------------+ | 1 | +-------------+ 1 row in set (0.00 sec) |