SQL 函數是資料轉換與業務邏輯表達的基石。本文彙整 MySQL 5.7/8.0 高頻函數,分為字串、日期時間、數值、流程控制四類,附帶實戰範例與避坑提示。
1. 字串函數
| 函數 | 用途 | 範例 |
CONCAT(s1,s2...) | 串聯字串 | CONCAT(name,'(',country,')') AS title |
SUBSTRING(str,pos,len) | 截取子串 | SUBSTRING(phone,1,3) |
TRIM([BOTH|LEADING|TRAILING] 'x' FROM str) | 去除首尾字元 | TRIM(' abc ') |
REPLACE(str,from,to) | 替換字串 | REPLACE(desc,'old','new') |
UPPER/LOWER | 大小寫轉換 | UPPER(email) |
LENGTH/CHAR_LENGTH | 位元組長度/字元長度 | CHAR_LENGTH(name) |
LOCATE(sub,str) | 尋找子串位置 | LOCATE('@',email) |
SOUNDEX(str) | 發音編碼 (模糊比對) | WHERE SOUNDEX(name)=SOUNDEX('Lee') |
2. 日期時間函數
| 函數 | 用途 | 範例 |
NOW() / SYSDATE() | 當前日期時間 | WHERE created_at > DATE_SUB(NOW(), INTERVAL 7 DAY) |
CURDATE() / CURTIME() | 當前日期/時間 | WHERE DATE(created_at) = CURDATE() |
DATE_FORMAT(dt, fmt) | 格式化輸出 | DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i') |
DATE_ADD/DATE_SUB | 日期加減 | DATE_ADD(NOW(), INTERVAL 1 MONTH) |
DATEDIFF(d1,d2) | 天數差 | DATEDIFF('2024-01-10','2024-01-01') |
YEAR/MONTH/DAY/HOUR/MINUTE/SECOND | 擷取單一欄位 | MONTH(created_at) |
DAYOFWEEK/WEEK/QUARTER | 週/季資訊 | WEEK(NOW()) |
日期查詢黃金法則
-- ❌ 錯誤:WHERE created_at = '2024-01-01' (忽略時分秒)
-- ✅ 正確:WHERE DATE(created_at) = '2024-01-01'
-- ✅ 正確:WHERE created_at BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59'
-- ✅ 最佳 (可用索引):WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02'
3. 數值函數
| 函數 | 用途 | 範例 |
ABS(x) | 絕對值 | ABS(balance) |
CEIL/FLOOR/ROUND | 進位/捨去/四捨五入 | ROUND(price,2) |
MOD(n,m) | 取餘 | MOD(id,100) |
RAND([seed]) | 隨機數 | ORDER BY RAND() |
POWER/EXP/LN/LOG/SQRT | 數學運算 | SQRT(distance) |
SIN/COS/TAN/PI | 三角函數 | PI() |
4. 流程控制函數
| 函數 | 語法 | 範例 |
IF(cond, t, f) | 三元運算 | IF(score>=60,'Pass','Fail') |
CASE WHEN ... THEN ... ELSE ... END | 多條件分支 | CASE WHEN age<18 THEN 'Minor' WHEN age<60 THEN 'Adult' ELSE 'Senior' END |
COALESCE(v1,v2,...) | 回傳第一個非 NULL | COALESCE(phone, email, 'N/A') |
NULLIF(v1,v2) | 相等回 NULL | NULLIF(end_date, start_date) |
避坑提醒
- 函數作用於索引欄位會導致索引失效 (如
WHERE DATE(created_at)=...),改用範圍查詢。
RAND() 在 ORDER BY 會全表掃描,大表禁用。
COALESCE 參數型別需一致,否則隱含轉換可能截斷資料。