NULL 代表「未知」或「不存在」,是資料庫中最容易導致邏輯錯誤的特殊值。本文系統整理 SQL Server 與 Oracle 的 NULL 處理函數、比較語法、排序行為差異,並提供跨平台統一排序的最佳實踐方案。
| 功能 | SQL Server | Oracle |
|---|---|---|
| 替換 NULL | ISNULL(expr, replacement) | NVL(expr, replacement) |
| 判斷 NULL | IS NULL / IS NOT NULL | IS NULL / IS NOT NULL |
| 多值優先取非 NULL | COALESCE(v1, v2, ...) | COALESCE(v1, v2, ...) |
-- SQL Server
SELECT ISNULL(price, 0.0) FROM orders;
-- Oracle
SELECT NVL(price, 0.0) FROM orders;
-- 跨平台通用(ANSI 標準)
SELECT COALESCE(price, 0.0) FROM orders;
-- 找出價格為 NULL 的訂單
SELECT * FROM orders WHERE price IS NULL;
-- 找出價格不為 NULL 的訂單
SELECT * FROM orders WHERE price IS NOT NULL;
這是跨平台遷移最常見的隱性 Bug:
ORDER BY col ASC 時 NULL 排在**最後**。ORDER BY col ASC 時 NULL 排在**最前**。-- SQL Server 測試
CREATE TABLE demo_orders (id INT NULL);
INSERT INTO demo_orders VALUES (1), (2), (NULL), (3);
SELECT id FROM demo_orders ORDER BY id;
-- 結果順序:NULL, 1, 2, 3
使用 CASE WHEN 顯式控制 NULL 排序位置,確保跨平台行為一致:
SELECT id
FROM demo_orders
ORDER BY CASE WHEN id IS NULL THEN 1 ELSE 0 END, id;
原理:先按「是否為 NULL」排序(非 NULL=0 優先),再按實際值排序。
SELECT id
FROM demo_orders
ORDER BY CASE WHEN id IS NULL THEN 0 ELSE 1 END, id;
-- 將 NULL 視為極大值 999999 排最後
SELECT id FROM demo_orders ORDER BY COALESCE(id, 999999);
-- 將 NULL 視為極小值 -999999 排最前
SELECT id FROM demo_orders ORDER BY COALESCE(id, -999999);
若欄位有索引,使用 CASE WHEN 或 COALESCE 可能導致**索引掃描**而非索引搜尋。大數據量時建議:
SUM/AVG/COUNT(col) 會自動跳過 NULL;COUNT(*) 計算全部列。WHERE x NOT IN (SELECT y ...) 若子查詢含 NULL,整個條件永遠為 UNKNOWN。改用 NOT EXISTS。'abc' + NULL = NULL;Oracle 'abc' || NULL = 'abc'。建議用 CONCAT 或 COALESCE。NULL 處理看似簡單,實則暗藏跨平台排序差異、聚合忽略、NOT IN 陷阱等坑點。掌握 ISNULL/NVL/COALESCE 三大替換函數、IS NULL 標準比較、CASE WHEN 顯式排序控制,並建立團隊「NULL 處理規範」(如預設值策略、排序約定),即可從根源消除此類 Bug。