NULLの特徴
NULLとは0でも空文字でもない値のことを指します。(イメージ的には存在しない値を分かりやすくするためにNULLというシールを貼っている状態のこと。)
例えば、財布の中身はいくら?という問いに対して下記の場合が値を保持しているということが証明できます。
- 財布の中身が0円であれば財布が空なので0円という値を保持。
- 10円が入っていれば10円という値を保持。
しかし、財布自体がなければ10円を保持することも0円を保持することもできません。
この財布がない状態の事をSQLの世界ではNULLと呼んでいます。
NULLが嫌い
「=」が使えない
SQLにおいて値の比較や参照において「=」を使用するのですが、NULLに「=」は使用できません。
NULLの特徴でもお話したとおり、NULLは値ではないため「=」「<」「>」などの演算子を使用することができません。値ではないものを比較しようとするとSQLさんに怒られます。
そのため、IS NULLという構文を用いて値の参照や比較を行います。
--名前が無い人の検索
SELECT name FROM family WHERE name IS NULL;
--名前がある人の検索
SELECT name FROM family WHERE name IS NOT NULL;
何もない状態を可視化するための目印なので値ではなく、名詞という認識のほうが良いです。
文字結合ができない
NULL+文字列の結合を行なうと異変が起きてしまいます。
MysqlにてNULL値と文字列をCONCAT関数を使用して文字列結合を行うと、NULL値を含む文字列はNULLになってしまいました。(数学で言うところの{数字×0=0}みたいな感じなんですね。)
mysql> SELECT * FROM BUSYO;
+----------+-----------------+
| busyo_no | busyo_name |
+----------+-----------------+
| 1 | 開発部 |
| 2 | デザイン部 |
| 3 | 営業部 |
| 4 | サービス部 |
| 5 | NULL |
+----------+-----------------+
5 rows in set (0.00 sec)
mysql> SELECT CONCAT(busyo_name,'hoge') FROM BUSYO;
+---------------------------+
| CONCAT(busyo_name,'hoge') |
+---------------------------+
| 開発部hoge |
| デザイン部hoge |
| 営業部hoge |
| サービス部hoge |
| NULL |
+---------------------------+
5 rows in set (0.00 sec)
Oracleにて、CONCAT('あいうえお',NULL);を実行すると{あいうえお’’}という結果が返ってきます。
値の並び順
ORDER BYによって値を並び替える時、NULL値を含む列の場合はNULL値が一番上(もしくは一番下)にきます。
値ではないのがNULLの特徴なので、比較して並べかえを実現する事はできないみたいです。
NULL値の順序を指定する場合、「NULLS FIRST(or LAST)」を指定することで思い通りの順序にすることが可能です。
SQL> select * from fruit2 order by name1;
NAME1 NAME2
---------- ----------
apple orange
apple apple
banana banana
banana apple
banana orange
orange orange
orange
SQL> select * from fruit2 order by name1 nulls first;
NAME1 NAME2
---------- ----------
orange
apple orange
apple apple
banana orange
banana banana
banana apple
orange orange
論理演算にNULLが紛れ込むとやっかい
WHERE句に下記のようなサブクエリを記述した際にサブクエリの結果がNULLを返すと意図しない結果が帰ってきます。
SQL>SELECT * FROM TEST1
WHERE no <(SELECT min(no) FROM TEST2);
NULLに比較演算子は使用できないため、サブクエリの結果がNULLになると大元のSQLは1行も返してくれません。
TEST2テーブルにNULLが存在しないと思いこんで上記SQL文を発行してしまうと想定外の結果が帰ってくるので気をつけましょう。
対策としては、サブクエリ内でNULL値を変換してくれるcoalesce関数などの使用がおすすめです。
他にも
まだ学習不足で確認ができていないのですが、
- インデックスとNULL
- NULLの便利な使用方法
などを今後追記していきます。