日常用語でnullを理解する(2)


SQLにおけるnullは「値があることは分かっているが、それが何なのかはわからない」という意味だ。
「値がない」という意味ではない、ということに注意しなくてはならない。

nullは「値がない」ではない

nullを「値がない」という意味だと考えてしまうと、

  • 'a'と'b'とnullを連結した結果が、nullになる
  • 1 + nullがnullになる

といったSQLの挙動の意味が理解できなくなる。


nullが「値がない」という意味なら

select 'a' || 'b' || null

の結果には少なくとも'ab'が含まれているはずあって、「値なし」になってしまうのはおかしい。
また

select 1 + null

の結果が「値なし」になってしまうのも何だかよくわからない。
つまりSQLは、nullを「値がない」という意味のものとしては扱わない。


が、「値がない(まだない or あり得ない)」という意味でnullを使う、ということは普通に行われているように見える。
ここに「nullは不可解な、恐ろしいものだ」と言われるようになった原因の一つがあると思う。

nullは「値はあるが、何かはわからない」という意味

ここで

select 'a' || 'b' || null

のnullは、「xかもしれないし、yyかもしれないし、zzzかもしれない。... 何だか分からない」という意味だ、と考え直してみる。
すると、'a', 'b', nullの連結結果は「abxかもしれないし、abyyかもしれない。... 何だか分からない」ということになる。
よって、結果もまたnull(=値はあるが、わからない)でよい、と理解できる。
同様に

select 1 + null

も、1に何だか分からない値を足したら、その結果もまた何だか分からない。なのでnullでよい、と理解できる。

nullは不可解じゃない

前回参照したページにあるSQLを日常語で解釈してみよう。


以下のSQLは、サブクエリが { 22, 23, null } という、nullを含む集合を返すために、結果が常に0件になる。

    • Bクラスの東京在住の生徒と年齢が一致しないAクラスの生徒を選択するSQL

SELECT *
FROM Class_A
WHERE age NOT IN ( SELECT age
FROM Class_B
  WHERE city = '東京' );

この挙動をどう解釈すればよいか。


Class_Aの生徒の年齢は 19, 21, 22 のいずれかである。
また、サブクエリが返すnullは「値がわからない。それは19かもしれない。21かもしれない。22かもしれない」という意味なので、Class_Aの生徒の年齢は、いずれもその「わからないもの」に一致する可能性がある*1
よって「Bクラスの東京在住の生徒と年齢が一致しない」ことを保障できるAクラスの生徒は存在しない。だから結果は0件になる。
人間である以上、実世界の生徒に年齢はかならずあるのだから、この結果は理にかなっている。

nullが不可解になるケース

上でも書いたけどnullを「値がない」という意味で使う、ということは普通に行われている。
例えば顧客マスタに法人客と個人客を両方放り込んで、個人にあって法人にない属性=例えば生年月日とかは、法人客のレコードではnullにしておくとか。
あるいは顧客マスタの住所1・住所2には市町村と番地を、住所3には建物と号室を入力する、というときに、一戸建てに住んでいる顧客は住所3をnullにするとか。


SQLはnullを「値がわからない」の意味で扱うので、「値がない」のnullをSQLに渡すと、その結果は意味不明になってしまう。
その話を次回書いて終わりにする予定。

*1:両者を比較した結果は「trueかもしれないし、falseかもしれない」=unknown