NULL値にもっと注意深くなろう
今回は値がないということに対する正しい挙動を学ぶことがゴールです。
プログラミング言語によって「値がない」ということをどう扱うかは様々です。
SQLではどのように扱われるでしょうか。
それはNULL
です。
- SQLは
NULL
と(false
、0
、空の文字列
)を区別します。 -
NULL
との四則演算の結果は必ずNULL
になります。決して0
の扱いではありません。-
coalesce
関数で0
に変換はできる
-
-
NULL
との文字結合もまたNULL
です。(DBの種類によっては違うそうです)
NULLを含む検索
SELECT * FROM Books WHERE category = 'comedy';
この検索を行ったとき、category
がNULL
の行は当然取得されません。
SELECT * FROM Books WHERE NOT (category = 'comedy');
この検索を行ったときもまた、category
がNULL
の行は取得されません。
ある値ではない
ということは等価演算になりますが
つまり、 NULL != 'comedy'
がTRUE
、もしくは
NULL == 'comedy'
がFALSE
を返せば良いのですが
NULL
との等価演算は決してTRUE
にはなりません。
どこまでいってもNULL
です。
MySQLには、NULL
に対応した演算子があります。
<=>
です。
SELECT * FROM Books WHERE category <=> NULL;
プリペアドステートメントにNULLを渡せるか
プリペアドステートメントで予約語であるNULL
を値として渡すには
bindValue()
を使うしかありません。第3引数に型を指定できるので
そこでPDO::PARAM_NULL'を指定してあげます。
excute`でそのまま渡すのでは対応ができないということです。
NULLから逃げるのも違う
そんなNULL
はTRUE
orFALSE
で扱えるわけでもないので
また別の値を使った独自のルールを使うことで対応しようとすることもあるでしょう。
例えば数字でステータスを表す時に
1以上は有効
、-1は存在しない
というルールを決めたとします。
得点計算をするカラムがそのように扱われていたとしたらどうなるでしょう。
もし仮に、平均や偏差値などを算出する際に
単純に-1
を計算に含めてしまうと、求めていない計算結果が出力されてしまいます。
ここでは、本来得点を意味するデータが入るところに
別論理の存在しているかどうか
を定義する-1
が混ざってしまっています。
これではまともなテーブル設計とは言えません。
アプリケーションレベルでも注意する必要のある厄介な仕様となってしまいます。
NULLを理解しよう
NULL
は真偽のロジックである2値論理
とは別の、3値論理
として理解する必要があります。
4値論理
とかもあるそうで。
参考
NULLと演算子
NULL
を使った計算がどうなるか、まとめてみましょう。
下記の計算結果は全てNULL
です。
NULL = 0
NULL = 123
NULL <> 123
NULL + 123 (四則演算全て)
NULL = NULL
NULL <> NULL
特に
NULL = NULL
はこういう論理です。
不明な値と不明な値を比較しても、等しいかどうかはわからない
NULL <> NULL
は
不明な値と不明な値を比較しても、等しくないかどうかはわからない
ということになります。
NULLと論理式
NULL AND TRUE
は、NULL
となります。
NULL AND FALSE
では、AND FALSE
でFALSE
が確定しているのでFALSE
になります。
NULL OR FALSE
はNULL
となります。
NULL OR TRUE
はOR TRUE
でTRUE
が確定しているのでTRUE
になります。
NOT (NULL)
は、NULL
になります。
AND FLASE
とOR TRUE
がキーですね。
これはそのまま覚えるのが良さそう。
NULLで検索したい時
MySQLにはNULL
で検索するための構文が用意されています。
それがIS NULL
です。
SELECT * FROM Books WHERE category IS NULL;
こう使います。
IS NOT NULL
も存在します。
呟き
思ったけど、NULL
って虚数
みたいな感覚で扱うとわかりやすいんじゃ??
###メモ
a<=>b
はaとbは等しい(NULLにも対応)
=> spaceship
というらしい
a<>b
はaとbは等しくない
知らなかった。