首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 空值(NULL)深度解析:特性、測試與實務應用全攻略

     編輯:Oracle 資料庫基礎

在資料庫世界裡,NULL 不只是「沒有值」這麼簡單——它代表「未知」或「不適用」,是關聯式資料庫理論的核心概念之一。Oracle 對 NULL 的處理有其獨特規則,若不深入理解,極易在查詢、統計、索引等環節踩坑。本文以經典 EMP 員工表為例,系統梳理 NULL 的生成機制、核心特性、測試方法、運算邏輯、函數行為、排序與索引特性,助你建立完整的 NULL 知識體系。

一、NULL 的生成與核心特性

1. NULL 如何產生?

  • 預設值:未加 NOT NULL 或 PRIMARY KEY 約束的欄位,插入資料時若未指定值,自動成為 NULL。
  • INSERT 隱式產生:INSERT INTO emp(empno, ename) VALUES (1, 'JIA');未列出的欄位全部變為 NULL。
  • 顯式指定:INSERT ... VALUES (..., NULL, ...);字元型也可用 ''(兩個單引號)表示。
  • UPDATE 置空:UPDATE emp SET comm = NULL WHERE empno = 7369。

2. NULL 的五大核心特性

特性說明實務影響
等價於「無值」非 0、非空字串、非空格不可用 =、!= 比較
三值邏輯比較結果為 NULL(非 TRUE/FALSE)WHERE 視為 FALSE,不報錯也不回傳列
排序最大ORDER BY col ASC 時 NULL 排最後需用 NULLS FIRST/LAST 明確控制
不可被索引B-tree 索引不儲存全 NULL 的鍵值WHERE col IS NULL 走全表掃描;但可建唯一索引(多筆 NULL 不違反唯一性)
運算傳染任何算術/字串運算含 NULL,結果皆為 NULLsal + comm 若 comm 為 NULL,總薪資變 NULL

二、NULL 測試:只能用 IS [NOT] NULL

錯誤寫法:

WHERE mgr = ''      -- 字元型空字串,非 NULL
WHERE mgr = NULL    -- 永遠回傳 UNKNOWN,等同 FALSE

正確寫法:

WHERE mgr IS NULL       -- 找出無主管的員工(如 KING)
WHERE mgr IS NOT NULL   -- 找出有主管的員工

DECODE 例外:DECODE(col, NULL, 'A', 'B') 視兩個 NULL 為相等,這是 Oracle 歷史相容設計。

三、NULL 與各類運算子的交互行為

1. 邏輯運算子(三值邏輯真值表)

運算NULL AND TRUENULL AND FALSENULL AND NULLNULL OR TRUENULL OR FALSENULL OR NULLNOT NULL
結果NULLFALSENULLTRUENULLNULLNULL

關鍵啟示:NULL AND FALSE = FALSE、NULL OR TRUE = TRUE 是僅有的「短路」情況;其餘含 NULL 運算皆產生 NULL,進而導致 WHERE 過濾掉該列。

2. 比較運算子詳細對照表

運算子類別表達式範例結果備註
IS [NOT] NULLa IS NULLTRUE唯一可靠測試
a IS NOT NULLFALSE
c IS NULLFALSE
c IS NOT NULLTRUE
= != > < >= <=a = NULLNULL含 NULL 必為 NULL
a > NULLNULL
c = NULLNULL
c > NULLNULL
IN (=ANY)a IN (10, NULL)NULL等價於 OR 串聯
c IN (10, NULL)TRUE
c IN (20, NULL)NULL
NOT IN (!=ALL)a NOT IN (20, NULL)NULL等價於 AND 串聯,極易踩坑
c NOT IN (20, NULL)FALSE
c NOT IN (10, NULL)NULL
ANY / SOMEa > ANY(5, NULL)NULL同 IN 邏輯
c > ANY(5, NULL)TRUE
c > ANY(15, NULL)NULL
ALLa > ALL(5, NULL)NULL同 NOT IN 邏輯
c > ALL(5, NULL)NULL
c > ALL(15, NULL)FALSE
(NOT) BETWEENa BETWEEN 5 AND NULLNULL展開為 >= AND <=
c BETWEEN 5 AND NULLNULL
c BETWEEN 15 AND NULLFALSE
a NOT BETWEEN 5 AND NULLNULL
c NOT BETWEEN 5 AND NULLNULL
c NOT BETWEEN 15 AND NULLTRUE

3. 算術與字串運算

  • 算術:NULL + 10 = NULL、sal + comm 任一為 NULL 則總和為 NULL。
  • 字串連接:Oracle 目前把空字串 '' 視同 NULL,故 ename || mgr 若 mgr 為 NULL,結果等同 ename(非標準 SQL 行為,未來版本可能改變)。

四、NULL 與函數:單列 vs 群組函數的差異

1. 單列函數(度量函數)

除 NVL、NVL2、COALESCE、TRANSLATE 外,參數為 NULL 時回傳 NULL。
例:ABS(comm)、UPPER(ename) 皆同理。

2. 群組函數(彙總函數)

預設忽略 NULL:COUNT(comm)、SUM(comm)、AVG(comm) 只統計非 NULL 列。
若需把 NULL 視為 0 參與計算,必須用 NVL(comm,0) 包裹。

實務陷阱:三種 SUM 寫法的差異

寫法邏輯NULL 處理
SUM(sal + comm)先逐列相加再彙總任一為 NULL → 該列不計入
SUM(sal) + SUM(comm)先各自彙總再相加各自忽略 NULL;若任一彙總為 NULL(如全 NULL),結果為 NULL
SUM(NVL(sal,0) + NVL(comm,0))先以 0 取代 NULL 再加總所有列皆參與,最直觀

五、其他實務特性

1. 排序時 NULL 最大

SELECT ename, comm FROM emp WHERE deptno = 30 ORDER BY comm;
-- 結果:0, 300, 500, 1400, NULL, NULL(NULL 排最後)

若需 NULL 排最前:ORDER BY comm NULLS FIRST。

2. NULL 不被索引 → 可建唯一索引

因 B-tree 不存全 NULL 鍵值,同一欄位允許無限筆 NULL 且不違反 UNIQUE 約束:

CREATE UNIQUE INDEX emp_comm_uq ON emp(comm);  -- 成功,即使 comm 有多筆 NULL

但查詢 WHERE comm IS NULL 無法使用此索引,仍需全表掃描。

六、最佳實務清單

  1. 測試 NULL 永遠用 IS NULL / IS NOT NULL。
  2. NOT IN 子查詢若可能回傳 NULL,改用 NOT EXISTS 或 LEFT JOIN ... IS NULL。
  3. 彙總前先 NVL(col, 0) 或 COALESCE,避免統計偏差。
  4. 字串連接建議用 CONCAT 或 || 搭配 NVL,明確控制 NULL 顯示。
  5. 需查詢 NULL 且效能敏感時,考慮函數索引:CREATE INDEX idx_emp_comm_null ON emp(CASE WHEN comm IS NULL THEN 1 END)。
  6. 資料模型階段即決定欄位是否允許 NULL,嚴謹使用 NOT NULL 約束,減少應用層防禦性程式碼。

掌握 NULL 的三值邏輯與傳染特性,是寫出正確、高效 Oracle SQL 的基石。願這份筆記能成為你開發時的隨身速查表。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved