在撰寫報表或統計查詢時,整數欄位參與四則運算若遇 NULL,結果會直接變成 NULL(NULL 具有「傳染性」)。這是導致財務報表、庫存試算錯誤的常見隱形殺手。本文透過實測案例示範問題、提供標準解法,並給出表設計與查詢撰寫的雙重防禦建議。
假設表 test_table 有兩個可為 NULL 的整數欄位 total、used:
id | total | used ---|-------|----- 1 | 100 | 20 2 | NULL | 10 3 | 50 | NULL 4 | NULL | NULL
SELECT id, total, used, (total - used) AS have FROM test_table;
id | total | used | have ---|-------|------|----- 1 | 100 | 20 | 80 2 | NULL | 10 | NULL -- 期望 90,實得 NULL 3 | 50 | NULL | NULL -- 期望 50,實得 NULL 4 | NULL | NULL | NULL
結論:任一運算元為 NULL,整個運算式結果即為 NULL。
SELECT id, IFNULL(total, 0) AS total, IFNULL(used, 0) AS used, (IFNULL(total, 0) - IFNULL(used, 0)) AS have FROM test_table;
SELECT id, COALESCE(total, 0) AS total, COALESCE(used, 0) AS used, (COALESCE(total, 0) - COALESCE(used, 0)) AS have FROM test_table;
id | total | used | have ---|-------|------|----- 1 | 100 | 20 | 80 2 | 0 | 10 | -10 -- 視業務邏輯決定是否合理 3 | 50 | 0 | 50 4 | 0 | 0 | 0
CREATE TABLE test_table ( id INT PRIMARY KEY AUTO_INCREMENT, total INT NOT NULL DEFAULT 0, used INT NOT NULL DEFAULT 0 );
優點:從源頭消除 NULL,查詢碼簡潔,效能最佳(無需函數呼叫)。
| 函數 | NULL 處理 | 備註 |
|---|---|---|
| SUM / AVG | 忽略 NULL | 全 NULL 群組回傳 NULL |
| COUNT(col) | 不計 NULL | COUNT(*) 計算列數含 NULL |
| MAX / MIN | 忽略 NULL | 全 NULL 回傳 NULL |
只有純量運算子(+ - * /)會讓 NULL 傳染,聚合函數多為忽略 NULL,但最終結果仍可能為 NULL,需視業務再包裹 IFNULL(SUM(x),0)。
「一份財務報表若因 NULL 導致試算不平,後果遠比修補查詢成本高昂。」
NOT NULL DEFAULT 0。DEFAULT 0 並 UPDATE SET col=0 WHERE col IS NULL,再 ALTER ... NOT NULL。COALESCE(col, 0) 肌肉記憶。將 NULL 視為「未知」而非「零」,並在邊界處理上建立統一規範,是資料品質管理的關鍵一環。