《Oracle 入门教程》第 09 篇 CASE 表达式
Posted 不剪发的Tony老师
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Oracle 入门教程》第 09 篇 CASE 表达式相关的知识,希望对你有一定的参考价值。
文章目录
Oracle 中的 CASE 表达式可以根据不同条件产生不同的结果,实现类似于编程语言中的 IF-THEN-ELSE 逻辑功能。例如,根据员工的 KPI 计算相应的涨薪幅度,根据考试成绩评出优秀、良好、及格等。
COALESCE 和 NULLIF 函数是两个简写形式的 CASE 表达式。另外,Oracle 还提供了专有的 NVL、NVL2 以及 DECODE 函数。
9.1 CASE 表达式
CASE 表达式支持两种形式:简单 CASE 表达式和搜索 CASE 表达式。
9.1.1 简单 CASE 表达式
简单 CASE 表达式的语法如下:
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
[ELSE default_result]
END
表达式的计算过程如下图所示:
首先计算 expression 的值;然后依次与 WHEN 列表中的值(value1,value2,…)进行比较,找到第一个相等的值并返回对应的结果(result1,result2,…);如果没有找到相等的值,返回 ELSE 中的默认结果;如果此时没有指定 ELSE,返回 NULL 值。
以下语句使用简单 CASE 表达式将员工的部门编号显示为相应的部门名称:
SELECT emp_name AS "员工姓名",
CASE dept_id
WHEN 1 THEN '行政管理部'
WHEN 2 THEN '人力资源部'
WHEN 3 THEN '财务部'
WHEN 4 THEN '研发部'
WHEN 5 THEN '销售部'
WHEN 6 THEN '保卫部'
ELSE '其他部门'
END AS "所在部门"
FROM employee;
员工姓名|所在部门 |
------|--------|
刘备 |行政管理部|
关羽 |行政管理部|
张飞 |行政管理部|
...
邓芝 |销售部 |
简雍 |销售部 |
孙乾 |销售部 |
首先,判断部门编号是否等于 1,等于就显示为“行政管理部”;否则,如果部门编号等于 2, 显示为“人力资源部”;依次类推;如果部门编号不等于 1 到 6 中的任何值,显示为“其他部门”。
CASE 表达式的一个常见应用就是实现表的行列转换。创建以下学生成绩表:
-- 创建成绩表 t_case,sname 为学生姓名,cname 为课程名称,score 为考试成绩
CREATE TABLE t_case(sname varchar(10), cname varchar(10), score int);
-- 插入测试数据
INSERT INTO t_case(sname, cname, score) VALUES ('张三', '语文', 80);
INSERT INTO t_case(sname, cname, score) VALUES ('李四', '语文', 77);
INSERT INTO t_case(sname, cname, score) VALUES ('王五', '语文', 91);
INSERT INTO t_case(sname, cname, score) VALUES ('张三', '数学', 85);
INSERT INTO t_case(sname, cname, score) VALUES ('李四', '数学', 90);
INSERT INTO t_case(sname, cname, score) VALUES ('王五', '数学', 60);
INSERT INTO t_case(sname, cname, score) VALUES ('张三', '英语', 81);
INSERT INTO t_case(sname, cname, score) VALUES ('李四', '英语', 69);
INSERT INTO t_case(sname, cname, score) VALUES ('王五', '英语', 82);
该表中的数据如下:
SELECT *
FROM t_case;
sname |cname |score|
------|-------|-----|
张三 |语文 | 80|
李四 |语文 | 77|
王五 |语文 | 91|
张三 |数学 | 85|
李四 |数学 | 90|
王五 |数学 | 60|
张三 |英语 | 81|
李四 |英语 | 69|
王五 |英语 | 82|
接下来我们利用 CASE 表达式将其转换为按列显示的形式:
SELECT sname,
sum(CASE cname WHEN '语文' THEN score ELSE 0 END) AS "语文",
sum(CASE cname WHEN '数学' THEN score ELSE 0 END) AS "数学",
sum(CASE cname WHEN '英语' THEN score ELSE 0 END) AS "英语"
FROM t_case
GROUP BY sname;
sname |语文|数学|英语|
------|---|---|---|
张三 | 80| 85| 81|
李四 | 77| 90| 69|
王五 | 91| 60| 82|
第一个 CASE 表达式用于获取学生的语文成绩,cname 等于“语文”就返回考试成绩,不是“语文”就记为 0 分;第二个和第三个 CASE 表达式分别用于获取数学和英语成绩。然后,使用 SUM 汇总函数和 GROUP BY 分组操作将每个学生的成绩合并成一条记录。
简单 CASE 表达式使用的是等值比较(=),只能处理简单的逻辑。如果想要进行复杂的逻辑处理,例如根据考试成绩评出优秀、良好、及格等,或者判断表达式的值是否为空,就需要使用更加强大的搜索 CASE 表达式。
9.1.2 搜索 CASE 表达式
搜索 CASE 表达式的语法如下:
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
[ELSE default_result]
END
表达式的计算过程如下图所示:
按照顺序依次计算每个分支中的条件(condition1,condition2,…),找到第一个结果为真的分支并返回相应的结果(result1,result2,…);如果没有任何条件为真,返回 ELSE 中的默认结果;如果此时没有指定 ELSE,返回 NULL 值。
所有的简单 CASE 表达式都可以替换为等价的搜索 CASE 表达式。我们可以将上一节的示例改写如下:
SELECT emp_name AS "员工姓名",
CASE
WHEN dept_id = 1 THEN '行政管理部'
WHEN dept_id = 2 THEN '人力资源部'
WHEN dept_id = 3 THEN '财务部'
WHEN dept_id = 4 THEN '研发部'
WHEN dept_id = 5 THEN '销售部'
WHEN dept_id = 6 THEN '保卫部'
ELSE '其他部门'
END AS "所在部门"
FROM employee;
首先,判断部门编号等于 1 是否成立(为真),成立就显示为“行政管理部”;否则,判断部门编号等于 2 是否成立, 成立就显示为“人力资源部”;依次类推;如果部门编号不等于 1 到 6 中的任何值,显示为“其他部门”。
以下查询按照考试分数对成绩进行评价:
SELECT sname AS "学生姓名",
cname AS "学科名称",
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 80 THEN '良好'
WHEN score >= 70 THEN '中等'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS "考试成绩"
FROM t_case;
学生姓名|学科名称|考试成绩|
-------|------|-------|
张三 |语文 |良好 |
李四 |语文 |中等 |
王五 |语文 |优秀 |
张三 |数学 |良好 |
李四 |数学 |优秀 |
王五 |数学 |及格 |
张三 |英语 |良好 |
李四 |英语 |及格 |
王五 |英语 |良好 |
CASE 表达式除了可以用于 SELECT 列表,也可以出现在其他子句中,例如 WHERE、GROUP BY、ORDER BY 等。以下语句使用 CASE 表达式实现了自定义的排序规则:
SELECT emp_name,
CASE emp_name
WHEN '刘备' THEN 1
WHEN '关羽' THEN 2
WHEN '张飞' THEN 3
ELSE 99
END AS num
FROM employee
ORDER BY CASE emp_name
WHEN '刘备' THEN 1
WHEN '关羽' THEN 2
WHEN '张飞' THEN 3
ELSE 99
END;
EMP_NAME|NUM|
--------+---+
刘备 | 1|
关羽 | 2|
张飞 | 3|
孙丫鬟 | 99|
...
关平 | 99|
我们通过 CASE 表达式将“刘备”编号为 1,“关羽”编号为 2,“张飞”编号为 3,其他人员编号为 99。
9.2 COALESCE 函数
COALESCE(expr1, …) 函数返回参数中第一个非空的值,它的等价 CASE 表达式如下:
CASE
WHEN expr1 IS NOT NULL THEN expr1
WHEN expr2 IS NOT NULL THEN expr2
WHEN expr3 IS NOT NULL THEN expr3
...
END
例如:
SELECT coalesce(NULL, NULL, 1), coalesce(NULL, NULL, NULL)
FROM dual;
COALESCE(NULL,NULL,1)|COALESCE(NULL,NULL,NULL)|
---------------------+------------------------+
1| |
9.3 NULLIF 函数
NULLIF(expr1,expr2) 函数的处理逻辑如下:如果表达式 expr1 和 expr2 相等,返回 NULL;否则,返回 expr1 的值。NULLIF 函数可以使用等价的 CASE 表达式进行表示:
CASE
WHEN expr1 = expr2 THEN NULL
ELSE expr1
END
NULLIF 函数的一个常见用途是防止除零错误:
-- 除零错误
SELECT 1 / 0
FROM dual;
SQL 错误 [1476] [22012]: ORA-01476: 除数为 0
SELECT 1 / NULLIF(0 , 0)
FROM dual;
1/NULLIF(0,0)|
-------------+
|
第一个语句会产生除零错误,第二个语句返回 NULL。
9.4 NVL 函数
NVL(expr1, expr2) 函数,它用于返回第一个非空的参数值,相当于只有两个参数的 COALESCE 函数。
以下查询返回了员工的总收入:
SELECT emp_name,
salary*12 + NVL(bonus, 0) AS "年收入"
FROM employee;
EMP_NAME|年收入 |
--------+------+
刘备 |370000|
关羽 |322000|
张飞 |298000|
诸葛亮 |296000|
黄忠 | 96000|
魏延 | 90000|
...
9.5 NVL2 函数
NVL2(expr1, expr2, expr3) 函数包含三个参数,如果第一个参数不为空,返回第二个参数的值;否则,返回第三个参数的值。以下查询同样返回员工的总收入:
SELECT emp_name,
NVL2(bonus, salary*12 + bonus, salary*12) AS "年收入"
FROM employee;
9.6 DECODE 函数
DECODE 函数可以实现类似于简单 CASE 表达式的功能:
DECODE(expression, value1, result1, value2, result2, ...[, default_result ])
该函数依次比较表达式 expression 与 valueN 的值,如果找到相等的值就返回对应的 resultN;如果没有匹配到任何相等的值,返回默认结果 default_result;如果此时没有提供 default_result,返回 NULL 值。
以下语句利用 DECODE 函数将员工的部门编号显示为相应的名称:
SELECT emp_name,
DECODE(dept_id, 1, '行政管理部',
2, '人力资源部',
3 ,'财务部',
4, '研发部',
5, '销售部',
6, '保卫部',
'其他部门') AS department
FROM employee;
该查询的结果与前文中的简单 CASE 表达式示例相同。DECODE 是 Oracle 专有函数,推荐大家使用标准的 CASE 表达式。
以上是关于《Oracle 入门教程》第 09 篇 CASE 表达式的主要内容,如果未能解决你的问题,请参考以下文章