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

MySQL 流程控制函數完全指南:IF、CASE、IFNULL、NULLIF 實戰範例與效能考量

     編輯:MySQL 綜合教學

前言:SQL 裡也能寫 if-else,但別濫用

MySQL 提供 IF()、CASE、IFNULL()、NULLIF() 四大流程控制函數,讓查詢具備條件邏輯能力。本文系統整理語法、型別推導規則、實戰範例、效能陷阱與最佳實踐,助你在正確場景用好它們。

四大函數語法與行為對照

函數語法回傳型別規則核心行為
IF(expr1, expr2, expr3)expr1 為真(非 0/非 NULL)回傳 expr2,否則 expr3expr2/expr3 型別較高者:STRING > REAL > INTEGER單條件三元運算
CASE 值 WHEN 比較值 THEN 結果 ... [ELSE 結果] END所有 THEN/ELSE 結果型別的通用集合值比較模式(類 switch)
CASE WHEN 條件 THEN 結果 ... [ELSE 結果] END同上條件判斷模式(類 if-else 鏈)
IFNULL(expr1, expr2)expr1 不為 NULL 回傳 expr1,否則 expr2兩者通用型別NULL 替換捷徑
NULLIF(expr1, expr2)expr1 = expr2 回傳 NULL,否則 expr1expr1 型別相等則 NULL,防除零錯誤

實戰範例庫

1. IF():性別碼轉中文、動態排序、條件聚合

-- 性別碼轉換
SELECT name, IF(sex=1, '男', '女') AS gender FROM users;

-- 動態排序:參數 @sort_desc=1 降序,0 升序
SELECT * FROM products ORDER BY IF(@sort_desc=1, price, -price);

-- 條件聚合:統計各狀態訂單數
SELECT 
  SUM(IF(status=1, 1, 0)) AS paid_count,
  SUM(IF(status=2, 1, 0)) AS shipped_count,
  SUM(IF(status=3, 1, 0)) AS refund_count
FROM orders;

2. CASE:複雜分組、動態分桶、避免除零

-- 價格區間分桶
SELECT 
  CASE 
    WHEN price < 100 THEN '低價'
    WHEN price < 500 THEN '中價'
    WHEN price < 1000 THEN '高價'
    ELSE '奢華'
  END AS price_tier,
  COUNT(*) AS cnt
FROM products GROUP BY price_tier;

-- 除零保護:NULLIF 讓分母為 0 時回傳 NULL,結果為 NULL 而非報錯
SELECT total_amount / NULLIF(order_count, 0) AS avg_order_value FROM sales;

3. IFNULL/COALESCE:預設值、多欄位取首個非空

-- 單欄位預設
SELECT IFNULL(phone, '未填寫') AS contact FROM users;

-- 多欄位取首個非空(COALESCE 為標準 SQL,支援 N 參數)
SELECT COALESCE(mobile, office_phone, home_phone, '無聯繫方式') AS contact FROM users;

型別推導陷阱:隱式轉換導致索引失效

-- 危險:IF 回傳字串,where 欄位為數字 → 隱式轉換 → 全表掃描
SELECT * FROM orders WHERE IF(status=1, 'paid', 'unpaid') = 'paid';  -- 錯誤示範

-- 正確:保持型別一致
SELECT * FROM orders WHERE status = 1;

鐵律:流程控制函數不要用在 WHERE/JOIN/INDEX 條件欄位上,僅用於 SELECT 列表、ORDER BY、GROUP BY、HAVING。

效能考量:何時用、何時避

場景建議理由
SELECT 列表轉換展示值✅ 推薦應用層省去轉換邏輯,網路傳輸量不增
條件聚合✅ 推薦單掃描完成多維統計,避免多次查詢
動態排序/分組⚠️ 謹慎可能導致 filesort,大資料集測試後再用
WHERE/JOIN 條件❌ 禁止破壞索引使用,隱式轉換,優化器無法推導
大表計算欄位❌ 避免CPU 開銷大,考慮物化視圖/應用層計算

進階:CASE 表達式 vs CASE 陳述式(預存程序專用)

-- 表達式(查詢中用):回傳值
SELECT CASE WHEN x>0 THEN '正' ELSE '非正' END;

-- 陳述式(預存程序中用):控制流程,不回傳值
CASE 
  WHEN v_action = 'insert' THEN INSERT ...;
  WHEN v_action = 'update' THEN UPDATE ...;
  ELSE SELECT 'invalid action';
END CASE;

結語

MySQL 流程控制函數是「查詢層小邏輯」的利器,用好能減少應用層往返、簡化報表 SQL、實現條件聚合。但嚴禁滲透到 WHERE/JOIN/索引欄位,否則效能災難立現。記住:CASE WHEN 處理多條件,IF() 處理單條件三元,COALESCE() 處理多欄位取首非空,NULLIF() 專治除零——各司其職,方為正道。

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