本文へスキップ
BecomeCoder

SQL データ操作 (DML)コース · 第1章 データを取り出す · レッスン5

NULL ― 「値が無い」を正しく扱う

ブラウザで完結

導入

データベースには、「まだ入力されていない」「そもそも該当しない」という状態があります。これを 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 でない)会員namecity を取り出してください。

ヒント1を見る

「値が有る」は IS NOT NULL です。WHERE city IS NOT NULL

ヒント2を見る

SELECT name, city FROM users WHERE city IS NOT NULL;

実際に動かしてみよう

下のエディタにクエリを書いて「実行」を押すと、ブラウザ内のSQLiteで結果が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう。

SQL — ブラウザ内で実行(SQLite)

ブラウザ内でSQLを動かす環境(SQLite)を読み込みます(初回のみ一瞬)。
スクロールして表示された時点でも自動で読み込まれます。