SQL中的CASE語法:強大而靈活的條件表達式

CASE 語法讓查詢裡的條件判斷變得直接,根據不同情況回傳不同結果,不需要在應用層多繞一圈。

CASE語法的基本結構

CASE 有兩種寫法:簡單 CASE 和搜索 CASE。

簡單CASE語法

1
2
3
4
5
6
CASE 表達式
WHEN1 THEN 結果1
WHEN2 THEN 結果2
...
[ELSE 其他結果]
END

搜索CASE語法

1
2
3
4
5
6
CASE
WHEN 條件1 THEN 結果1
WHEN 條件2 THEN 結果2
...
[ELSE 其他結果]
END

簡單 CASE 是對單一表達式做等值比對,搜索 CASE 則每個 WHEN 都是獨立條件,能處理範圍、NULL、複合邏輯,彈性更大。

CASE語法的特點

  • 靈活:條件邏輯可以很複雜,包含範圍、複合條件、NULL 判斷
  • 可讀:比一堆巢狀 IF 或應用層後處理清楚
  • 通用:SELECT、WHERE、ORDER BY、GROUP BY、UPDATE 都能用

實際應用場景

例子1:根據成績分級

1
2
3
4
5
6
7
8
9
10
11
SELECT 
學生姓名,
分數,
CASE
WHEN 分數 >= 90 THEN 'A'
WHEN 分數 >= 80 THEN 'B'
WHEN 分數 >= 70 THEN 'C'
WHEN 分數 >= 60 THEN 'D'
ELSE 'F'
END AS 等級
FROM 學生成績表;

例子2:根據部門計算不同的薪資增長

不同部門套不同的調薪倍率:

1
2
3
4
5
6
7
8
9
10
11
SELECT 
員工姓名,
部門,
目前薪資,
CASE 部門
WHEN '銷售' THEN 目前薪資 * 1.1
WHEN '技術' THEN 目前薪資 * 1.05
WHEN '行政' THEN 目前薪資 * 1.03
ELSE 目前薪資
END AS 調整後薪資
FROM 員工資料表;

例子3:在GROUP BY中使用CASE

CASE 也可以放在 GROUP BY 裡,按自訂規則分組。注意標準 SQL 不允許在 GROUP BY 直接引用 SELECT 裡定義的別名,所以 CASE 表達式要重複寫一次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT 
CASE
WHEN 年齡 < 18 THEN '未成年'
WHEN 年齡 BETWEEN 18 AND 65 THEN '成年'
ELSE '銀髮族'
END AS 年齡組,
COUNT(*) AS 人數
FROM 客戶資料表
GROUP BY
CASE
WHEN 年齡 < 18 THEN '未成年'
WHEN 年齡 BETWEEN 18 AND 65 THEN '成年'
ELSE '銀髮族'
END;

如果不想重複,可以用 CTE 或子查詢先把 CASE 結果計算出來,外層再 GROUP BY 別名。

CASE語法在UPDATE語句中的應用

UPDATE 裡用 CASE 可以一次根據條件更新多筆資料,比逐筆 UPDATE 省很多往返次數。

基本語法

1
2
3
4
5
6
7
8
UPDATE 資料表
SET 欄位 = CASE
WHEN 條件1 THEN1
WHEN 條件2 THEN2
...
ELSE 預設值
END
WHERE 條件;

例子1:根據員工表現更新薪資

1
2
3
4
5
6
7
UPDATE 員工資料表
SET 薪資 = CASE 表現評級
WHEN 'A' THEN 薪資 * 1.1
WHEN 'B' THEN 薪資 * 1.05
WHEN 'C' THEN 薪資 * 1.02
ELSE 薪資
END;

A 級加薪 10%,B 級 5%,C 級 2%,其餘不動。

例子2:根據庫存量更新產品狀態

1
2
3
4
5
6
7
UPDATE 產品資料表
SET 狀態 = CASE
WHEN 庫存量 = 0 THEN '缺貨'
WHEN 庫存量 BETWEEN 1 AND 10 THEN '低庫存'
WHEN 庫存量 BETWEEN 11 AND 50 THEN '適中'
ELSE '充足'
END;

例子3:在單一UPDATE語句中更新多個欄位

CASE 在 SET 裡可以同時處理多個欄位:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
UPDATE 訂單資料表
SET
處理狀態 = CASE
WHEN 付款狀態 = '已付款' AND 運送狀態 = '已發貨' THEN '已完成'
WHEN 付款狀態 = '已付款' AND 運送狀態 = '準備中' THEN '處理中'
WHEN 付款狀態 = '未付款' THEN '等待付款'
ELSE '處理中'
END,
優先級 = CASE
WHEN 訂單金額 > 10000 THEN '高'
WHEN 訂單金額 BETWEEN 5000 AND 10000 THEN '中'
ELSE '低'
END
WHERE 訂單日期 = CURRENT_DATE;

使用CASE進行UPDATE時的注意事項

  1. 效能考量:大型資料表上跑複雜 CASE UPDATE 會有壓力,可以考慮分批處理或確認相關欄位有索引。

  2. 資料一致性:確認 CASE 涵蓋了所有可能的情況,漏掉的條件會落進 ELSE,沒寫 ELSE 則回傳 NULL,悄悄蓋掉原有資料。

  3. 交易管理:大規模或關鍵更新記得包在 Transaction 裡,出錯才能 ROLLBACK。

  4. 先跑 SELECT 預覽:正式 UPDATE 前,把相同的 CASE 邏輯放進 SELECT 看結果是否符合預期,確認後再執行。