🙆

nullのカラムと比較するとnullになる話

2020/09/29に公開

MySQLで「NOT no = 1」といったWHERE句を指定したときに、NULLが入っているレコードも取れてくると思ったのですが取れてきませんでした。

検索結果にNULLのレコードが無い

次のテーブルtestに、レコードが3つあるとします。
noに1, 2, NULLが入っています。

mysql> desc test;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| no    | int(11) | YES  |     | NULL    |       |
| name  | text    | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> SELECT * FROM test;
+------+-----------+
| no   | name      |
+------+-----------+
|    1 | test1     |
|    2 | test2     |
| NULL | test null |
+------+-----------+
3 rows in set (0.01 sec)

この状態で「WHERE NOT no = 1」を実行すると、no=2のレコードのみが反応しました。

mysql> SELECT * FROM test WHERE NOT no = 1;
+------+-------+
| no   | name  |
+------+-------+
|    2 | test2 |
+------+-------+
1 row in set (0.00 sec)

no=1ではないレコードとして、no=NULLのレコードも取得できると思っていましたが取れてきませんでした。

比較結果がNULLになるみたい

判定の状況を見てみます。
SELECT文に判定式を書いてみると、NULLの場合はNULLと出てきます。

mysql> SELECT no, no=1 FROM test;
+------+------+
| no   | no=1 |
+------+------+
|    1 |    1 |
|    2 |    0 |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)

なのでNULL許可されているカラムでno=1ではないレコードを検索するためには、no IS NULLを別途指定する必要があります。

mysql> SELECT * FROM test WHERE NOT no = 1 OR no IS NULL;
+------+-----------+
| no   | name      |
+------+-----------+
|    2 | test2     |
| NULL | test null |
+------+-----------+
2 rows in set (0.00 sec)

NULL値との比較はNULLになる

ドキュメントには次のように記載されています。

SQL では、NULL 値はほかの値 (NULL を含む) との比較で true になることはありません。NULL を含む式は、式に関連する演算子および関数のドキュメントに示されている場合を除き、常に NULL 値を生成します。次の例のすべてのカラムは NULL を返します。

なので、NOT判定しようが関係なく、 常にfalse となるため検索結果に含まれないみたいです。

参考

Discussion