Contents

[SQL]比較null不能用等於

在 SQL 中,NULL 代表「未知」或「不存在」的值,它的行為與一般資料型別完全不同,常常是 bug 的來源。

NULL 的特殊性

NULL 不等於任何值,包括它自己

1
2
3
4
SELECT NULL = NULL;     -- 結果:NULL(不是 TRUE!)
SELECT NULL != NULL;    -- 結果:NULL
SELECT NULL = 0;        -- 結果:NULL
SELECT NULL = '';       -- 結果:NULL

這是因為 SQL 採用三值邏輯(Three-Valued Logic):TRUE、FALSE、NULL(UNKNOWN)。任何值與 NULL 比較,結果都是 NULL(UNKNOWN),而非 TRUE 或 FALSE。

正確用法:IS NULL 與 IS NOT NULL

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- ✅ 正確:查詢 email 為空的使用者
SELECT * FROM users WHERE email IS NULL;

-- ✅ 正確:查詢 email 有值的使用者
SELECT * FROM users WHERE email IS NOT NULL;

-- ❌ 錯誤:永遠不會回傳任何結果
SELECT * FROM users WHERE email = NULL;

-- ❌ 錯誤:永遠不會回傳任何結果
SELECT * FROM users WHERE email != NULL;

WHERE 條件中的陷阱

1
2
3
4
5
6
-- 假設 age 欄位有些資料是 NULL
-- 這個查詢不會包含 age 為 NULL 的資料
SELECT * FROM users WHERE age != 18;

-- 如果要包含 NULL,要明確處理
SELECT * FROM users WHERE age != 18 OR age IS NULL;

COALESCE 與 NULL 替換

COALESCE 函式可以將 NULL 替換為預設值:

1
2
3
4
5
-- 若 nickname 為 NULL,改顯示 username
SELECT COALESCE(nickname, username) AS display_name FROM users;

-- 計算時避免 NULL 影響結果
SELECT COALESCE(score, 0) + bonus FROM results;

應該避免使用 NULL 嗎?

這是資料庫設計上的經典爭議:

避免 NULL 的理由:

  • 三值邏輯複雜,容易出錯
  • 聚合函式(COUNTSUMAVG)會忽略 NULL,行為不直觀
  • JOIN 時 NULL 欄位不會匹配

接受 NULL 的理由:

  • 有些資料本來就是「未知」或「不適用」,NULL 語意最準確
  • 強制給預設值(如 0 或空字串)可能造成語意混淆

實務上建議:盡量在重要欄位加上 NOT NULL 約束,並用合理的預設值取代,以減少 NULL 帶來的複雜性。

參考資料