MySQL 提供四大流程控制函數,可在 SQL 查詢中實現條件邏輯,避免應用層往返:
CASE 值
WHEN 比較值1 THEN 結果1
WHEN 比較值2 THEN 結果2
...
[ELSE 預設結果]
END
CASE
WHEN 條件1 THEN 結果1
WHEN 條件2 THEN 結果2
...
[ELSE 預設結果]
END
-- 簡單 CASE:成績等級
SELECT score,
CASE score
WHEN 100 THEN '完美'
WHEN 90 THEN '優秀'
ELSE '普通'
END AS 等級
FROM exams;
-- 搜尋 CASE:區間判斷
SELECT score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 60 THEN 'C'
ELSE 'D'
END AS 等級
FROM exams;
-- 在 UPDATE 中使用
UPDATE products
SET status = CASE
WHEN stock = 0 THEN '缺貨'
WHEN stock < 10 THEN '庫存不足'
ELSE '正常'
END;
IF(條件, 真值, 假值)
SELECT IF(0.1, '真', '假'); -- '假'!0.1 轉整數為 0
SELECT IF(0.1 <> 0, '真', '假'); -- '真' 比較運算保留浮點精度
⚠️ 永遠使用比較運算子(<> 0, IS NOT NULL 等)而非直接放數值/字串。
-- 標記 VIP 客戶
SELECT name,
IF(total_spent > 10000, 'VIP', '一般') AS 客戶等級
FROM customers;
-- 安全除法(避免除零)
SELECT IF(divisor = 0, NULL, dividend / divisor) AS result
FROM calculations;
-- 巢狀 IF(不建議超過 2 層)
SELECT IF(score >= 90, 'A', IF(score >= 60, 'B', 'C')) AS grade;
IFNULL(expr1, expr2) -- expr1 不為 NULL 回傳 expr1,否則回傳 expr2
-- 顯示暱稱,無則顯示帳號
SELECT IFNULL(nickname, username) AS 顯示名稱 FROM users;
-- 計算總銷售額,無銷售記錄顯示 0
SELECT COALESCE(SUM(amount), 0) AS total_sales FROM orders WHERE user_id = 1;
-- IFNULL vs COALESCE:COALESCE 支援多參數,標準 SQL
SELECT COALESCE(mobile, phone, email, '無聯絡方式') FROM contacts;
NULLIF(expr1, expr2) -- 相等回 NULL,否則回 expr1
-- 等價於 CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END
-- 避免除零錯誤(分母為 0 時回 NULL)
SELECT 100 / NULLIF(divisor, 0) FROM calculations;
-- 空字串轉 NULL(匯入清洗常用)
SELECT NULLIF(TRIM(name), '') FROM raw_data;
-- 移除特定預設值
SELECT NULLIF(status, 'default') FROM settings;
SELECT
product_name,
-- 庫存狀態
CASE
WHEN stock = 0 THEN '缺貨'
WHEN stock < reorder_level THEN '需補貨'
ELSE '正常'
END AS stock_status,
-- 促銷價格(有促銷用促銷價,否則原價)
IFNULL(promo_price, price) AS current_price,
-- 折扣率(無折扣顯示 0)
IFNULL(discount_rate, 0) AS discount,
-- 利潤率(成本為 0 時回 NULL 避免除零)
(price - cost) / NULLIF(cost, 0) * 100 AS profit_margin_pct
FROM products;
IF(divisor=0, NULL, ...) 更簡潔<?php
$conn = new mysqli("localhost", "user", "pass", "shop");
$sql = "SELECT
id, name, price,
CASE
WHEN price > 1000 THEN '高價'
WHEN price > 500 THEN '中價'
ELSE '低價'
END AS price_tier,
IF(stock > 0, '有貨', '缺貨') AS availability,
IFNULL(sale_price, price) AS final_price
FROM products
ORDER BY price_tier, final_price";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
echo "{$row['name']} | {$row['price_tier']} | {$row['availability']} | NT$ {$row['final_price']}
";
}
$conn->close();
?>
善用流程控制函數,讓 SQL 直觀表達業務邏輯,減少應用程式複雜度,提升查詢效能與可維護性!