Query Go
NULL を扱う - NULL の扱い の使い方・オプション・サンプル

NULL を扱う - NULL の扱い

3 値論理、IS NULL / IS NOT NULL、COALESCE / NULLIF / NVL、NULL による集約や比較のハマりどころ

概念図

NULL の扱い diagram

構文

sql
col IS NULL / col IS NOT NULL / COALESCE(a, b, ...) / NULLIF(a, b)

サンプル

COALESCE でフォールバック、NULLIF で空文字を NULL に正規化、IS NULL で論理削除除外

sql
SELECT id,
  COALESCE(nickname, name, 'Anonymous') AS display_name,
  NULLIF(phone, '')                     AS phone_clean
FROM users
WHERE deleted_at IS NULL;

NULL と 3 値論理

SQL の真偽値は TRUE / FALSE / UNKNOWN の 3 つあります。NULL との比較(col = 1 など)はすべて UNKNOWN になり、WHERE では除外されます。

  • NULL = NULL → UNKNOWN(TRUE ではない)
  • NULL <> 1 → UNKNOWN(FALSE ではない)
  • NULL AND TRUE → UNKNOWN、NULL OR TRUE → TRUE

IS NULL / IS NOT NULL

NULL かどうかを判定するには 必ず IS NULL / IS NOT NULL を使います。= NULL / <> NULL は常に UNKNOWN を返すため、意図した結果になりません。

sql
-- 間違い: 何もヒットしない
SELECT * FROM users WHERE deleted_at = NULL;

-- 正しい
SELECT * FROM users WHERE deleted_at IS NULL;

COALESCE / NULLIF / NVL

  • COALESCE(a, b, c, ...): 左から見て最初に NULL でない値を返す。標準 SQL、全 RDBMS で利用可
  • NULLIF(a, b): a = b なら NULL、そうでなければ a。ゼロ除算の回避(NULLIF(divisor, 0))や空文字の正規化に便利
  • NVL(a, b) は Oracle 方言(2 引数版の COALESCE)。IFNULL(a, b) は MySQL / SQLite、ISNULL(a, b) は SQL Server。移植性が必要なら COALESCE を使う。RDBMS 間の差分は RDBMS 方言早見表 にまとめています
sql
-- ゼロ除算を NULL にする
SELECT amount / NULLIF(quantity, 0) AS unit_price FROM items;

集約関数と NULL

集約関数は基本的に NULL を無視します。

  • COUNT(*): NULL も含めて行数を数える
  • COUNT(col): col が NULL でない行だけ数える
  • SUM / AVG / MAX / MIN: NULL は除外して計算(全行 NULL だと結果も NULL)
  • AVG は NULL を 分母にも入れないので、ゼロ扱いにしたいなら COALESCE(col, 0) でラップする

落とし穴: NOT IN と NULL

サブクエリの結果に NULL が混ざっていると NOT IN一行も返さなくなることがあります。x NOT IN (1, 2, NULL)x <> 1 AND x <> 2 AND x <> NULL と展開され、最後が UNKNOWN なので全体も UNKNOWN になるためです。

安全のため、NULL を含み得る列には NOT EXISTS を使うか、サブクエリ側で WHERE col IS NOT NULL を明示してください。

関連トピック