NULLが嫌いと感じる理由をまとめてみた

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に対して「=」ではなくISを使用していることから
何もない状態を可視化するための目印なので値ではなく、名詞という認識のほうが良いです。

文字結合ができない

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ではNULL値を空文字として扱うという事です。
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の便利な使用方法

などを今後追記していきます。

Twitterでフォローしよう

おすすめの記事