導入
データベースには、「まだ入力されていない」「そもそも該当しない」という状態があります。これを NULL(ヌル)といいます。NULL は「0」でも「空文字」でもなく、「値が無い」という特別な状態です。この扱いを間違えると、実務で「あるはずのデータが取れない」という定番のハマりに陥ります。ここで正しくつかんでおきましょう。
説明
NULL がやっかいなのは、比較しても「真」にならないことです。NULL は「不明な値」なので、「不明 = 何か」も「不明 < 何か」も、答えは「真とも偽とも言えない(= unknown)」になります。だから = NULL では絶対に引っかかりません。
flowchart TB
Q["category_id = NULL と書くと?"]
Q --> U["結果は unknown(真にならない)<br/>→ 1行も返らない!"]
Q2["正しくは IS NULL / IS NOT NULL を使う"]
Q2 --> OK["category_id IS NULL … 値が無い行<br/>category_id IS NOT NULL … 値が有る行"]
NULL の判定には、専用の IS NULL / IS NOT NULL を使います。
-- カテゴリが未設定(NULL)の商品
SELECT id, name FROM products WHERE category_id IS NULL;
-- カテゴリが設定済みの商品
SELECT id, name, category_id FROM products WHERE category_id IS NOT NULL;
このデータでは全商品にカテゴリが入っているので、
IS NULLは0件・IS NOT NULLは全件になります。試しにINSERT INTO products (id, name, price) VALUES (99, 'テスト品', 100);でcategory_idを省いた行を足すと、その行だけIS NULLで拾えます(カテゴリ列に値を入れなかったので NULL になります)。
もうひとつの落とし穴。NULL の入った列を条件にすると、「等しくない」条件からもこぼれ落ちます。たとえば WHERE city <> '東京' は、city が NULL の行を含みません(NULL は「東京と違う」とも判定されないため)。NULL も拾いたいなら WHERE city <> '東京' OR city IS NULL のように明示します。
NULL を別の値に置き換えて表示したいときは COALESCE(列, 代わりの値) が便利です。「NULL なら『未分類』と出す」ならこう書きます。
SELECT name, COALESCE(category_id, 0) AS カテゴリ FROM products;
やってみよう
初期表示の IS NOT NULL を実行し、全商品が出ることを確認しましょう。次に WHERE category_id = NULL(誤り)に書き換えて実行し、1行も返らないことを体験してください。「NULL は = で比較できない」――この失敗を一度味わっておくと、実務で必ず役立ちます。
演習
users テーブルから、都市(city)が入力されている(NULL でない)会員の name と city を取り出してください。
ヒント1を見る
「値が有る」は IS NOT NULL です。WHERE city IS NOT NULL
ヒント2を見る
SELECT name, city FROM users WHERE city IS NOT NULL;