DECODE(expr, search1, result1 [, search2, result2 ...] [, default])
-- 依次比較 expr = search_i,匹配返回 result_i,全不匹配返回 default (默認 NULL)
SELECT id,
user_name,
oper_time,
oper_type,
DECODE(oper_flag, '1', '成功', '0', '失敗', '未知') AS flag_desc
FROM sec_log_operation;
現象:DECODE(oper_flag, 1, '成功', '失敗') 報錯 ORA-01722: invalid number。
原因:oper_flag VARCHAR2 列含非數字值 (如 '失敗'),Oracle 嘗試將 expr 隱式轉換為 NUMBER 與 search=1 比較,遇到非數字拋異常。
-- 正確:搜索值加引號,強制字符串比較
DECODE(oper_flag, '1', '成功', '0', '失敗', '未知')
DECODE(NULL, NULL, 'is null', 'not null') → 'is null' (Oracle 視 NULL=NULL 為真)。CASE WHEN NULL IS NULL THEN ... 同樣為真,但 CASE col WHEN NULL THEN ... 為假 (簡單 CASE 用 = 比較)。NVL(col,'@NULL@') 或搜索 CASE。result_i 和 default 隱式轉換為最高優先級類型 (NUMBER > DATE > CHAR)。result1 是 NUMBER、result2 是 VARCHAR2 → 返回 NUMBER,VARCHAR2 隱式 TO_NUMBER,可能報錯。TO_CHAR 統一返回字符串,或顯式 CAST。| 場景 | 推薦 | 理由 |
|---|---|---|
| 簡單等值映射 (≤10 分支) | DECODE / CASE | 解析快、可讀性好 |
| 範圍/複合條件 | CASE (搜索) | DECODE 不支持 |
| 大量映射 (>50) | 查找表 JOIN | 避免巨大解析樹、便於維護 |
| 需 NULL=NULL 匹配 | DECODE / NVL+CASE | CASE 簡單形式不支持 |
SELECT deptno,
SUM(DECODE(job,'CLERK',sal)) AS clerk_sal,
SUM(DECODE(job,'SALESMAN',sal)) AS sales_sal,
SUM(DECODE(job,'MANAGER',sal)) AS mgr_sal
FROM emp
GROUP BY deptno;
11g+ 推薦用 PIVOT:SELECT * FROM emp PIVOT (SUM(sal) FOR job IN ('CLERK','SALESMAN','MANAGER'))。