NULL 代表「值未知」,非空字串、非零、非假。任何與 NULL 的比較(=、!=、<、>)結果皆為 NULL(視為假),這是 SQL 三值邏輯的核心。本文系統整理 NULL 判斷運算子、索引存儲特性、聚合函數行為、應用層處理模式與避坑清單。
| 運算子 | 語法 | 結果(當 col 為 NULL) | 說明 |
|---|---|---|---|
| IS NULL | col IS NULL | TRUE | 標準檢查 |
| IS NOT NULL | col IS NOT NULL | FALSE | 標準檢查 |
| <=> | col <=> val | NULL <=> NULL 為 TRUE | 空值安全相等,等同 (col = val) OR (col IS NULL AND val IS NULL) |
| COALESCE | COALESCE(col, 'default') | 'default' | 回傳第一個非 NULL 參數 |
| IFNULL | IFNULL(col, 'default') | 'default' | MySQL 專用,兩參數 |
| NULLIF | NULLIF(col, val) | 若 col=val 則 NULL 否則 col | 反向操作 |
-- ❌ 錯誤:任何與 NULL 比較皆為 NULL(假) SELECT * FROM t WHERE col = NULL; SELECT * FROM t WHERE col != NULL; SELECT * FROM t WHERE col = ''; -- 空字串 ≠ NULL -- ✅ 正確 SELECT * FROM t WHERE col IS NULL; SELECT * FROM t WHERE col IS NOT NULL; SELECT * FROM t WHERE col <=> NULL; -- 等同 IS NULL -- ✅ 空值安全相等(參數可能為 NULL) SELECT * FROM t WHERE col <=> ?; -- 預處理參數安全
WHERE col IS NULL 可走索引。ANALYZE TABLE 計算 Cardinality 時會統計 NULL 比例,影響執行計劃選擇。| 函數 | NULL 處理 | 範例結果 |
|---|---|---|
| COUNT(*) | 計算行數,包含 NULL | 10 行 → 10 |
| COUNT(col) | 計算非 NULL 個數 | 3 NULL, 7 非 NULL → 7 |
| SUM/AVG | 忽略 NULL | SUM(1,2,NULL)=3, AVG=1.5 |
| MAX/MIN | 忽略 NULL,全 NULL 回傳 NULL | MAX(1,NULL)=1 |
| GROUP_CONCAT | 忽略 NULL | 'a,b' (跳過 NULL) |
$stmt = $pdo->prepare('SELECT * FROM users WHERE status <=> ?');
$stmt->execute([$status]); // $status 可能為 null
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
from sqlalchemy import or_ # 參數可能為 None q = session.query(User).filter(or_(User.status == status, User.status.is_(None)))
WHERE id NOT IN (SELECT cid FROM t WHERE cid IS NULL) → 永無結果。改用 NOT EXISTS 或 LEFT JOIN ... WHERE t.cid IS NULL。ORDER BY col IS NULL, col ASC 控制位置。WHERE col IS NOT NULL 部分索引(8.0+ 支援)。JSON_EXTRACT(doc, '$.a') 回傳 NULL 可能是鍵不存在或值為 null,用 JSON_CONTAINS_PATH 區分。理解 NULL 的三值邏輯,並在查詢、索引、應用層統一處理規範,能消除一大類難以復現的資料不一致 Bug。