文章目录

  • 9.1 CASE 表达式
    • 9.1.1 简单 CASE 表达式
    • 9.1.2 搜索 CASE 表达式
  • 9.2 COALESCE 函数
  • 9.3 NULLIF 函数
  • 9.4 NVL 函数
  • 9.5 NVL2 函数
  • 9.6 DECODE 函数

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 expressionWHEN value1 THEN result1WHEN value2 THEN result2...[ELSE default_result]
END

表达式的计算过程如下图所示:


首先计算 expression 的值;然后依次与 WHEN 列表中的值(value1,value2,…)进行比较,找到第一个相等的值并返回对应的结果(result1,result2,…);如果没有找到相等的值,返回 ELSE 中的默认结果;如果此时没有指定 ELSE,返回 NULL 值。

以下语句使用简单 CASE 表达式将员工的部门编号显示为相应的部门名称:

SELECT emp_name AS "员工姓名",CASE dept_idWHEN 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 表达式的语法如下:

CASEWHEN condition1 THEN result1WHEN condition2 THEN result2...[ELSE default_result]
END

表达式的计算过程如下图所示:


按照顺序依次计算每个分支中的条件(condition1,condition2,…),找到第一个结果为真的分支并返回相应的结果(result1,result2,…);如果没有任何条件为真,返回 ELSE 中的默认结果;如果此时没有指定 ELSE,返回 NULL 值。

所有的简单 CASE 表达式都可以替换为等价的搜索 CASE 表达式。我们可以将上一节的示例改写如下:

SELECT emp_name AS "员工姓名",CASEWHEN 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 "学科名称",CASEWHEN 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_nameWHEN '刘备' THEN 1WHEN '关羽' THEN 2WHEN '张飞' THEN 3ELSE 99END AS num
FROM employee
ORDER BY CASE emp_nameWHEN '刘备' THEN 1WHEN '关羽' THEN 2WHEN '张飞' THEN 3ELSE 99END;
EMP_NAME|NUM|
--------+---+
刘备     |  1|
关羽     |  2|
张飞     |  3|
孙丫鬟   | 99|
...
关平     | 99|

我们通过 CASE 表达式将“刘备”编号为 1,“关羽”编号为 2,“张飞”编号为 3,其他人员编号为 99。

9.2 COALESCE 函数

COALESCE(expr1, …) 函数返回参数中第一个非空的值,它的等价 CASE 表达式如下:

CASEWHEN expr1 IS NOT NULL THEN expr1WHEN expr2 IS NOT NULL THEN expr2WHEN 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 表达式进行表示:

CASEWHEN expr1 = expr2 THEN NULLELSE expr1
END

NULLIF 函数的一个常见用途是防止除零错误:

-- 除零错误
SELECT 1 / 0
FROM dual;
SQL 错误 [1476] [22012]: ORA-01476: 除数为 0SELECT 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 表达式相关推荐

  1. 《Oracle 入门教程》第 01 篇 专栏介绍

    文章目录 专栏背景 专栏内容 专栏寄语 大家好,我是只谈技术不剪发的 Tony 老师.欢迎来到我的专栏<Oracle 入门教程>!本专栏主要面向 Oracle 数据库的初学者,包括初级 D ...

  2. Linux Capabilities 入门教程--进阶实战篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 Linux Capabilities 入门教程:进阶实战篇 ...

  3. Systemd入门教程:命令篇

    Systemd入门教程:命令篇 转自:http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html 作者: 阮一峰 日期: ...

  4. Systemd 入门教程:实战篇

    Systemd 入门教程:实战篇 原文出处: 阮一峰(@ruanyf)   http://blog.jobbole.com/98671/?utm_source=blog.jobbole.com& ...

  5. Linux Capabilities 入门教程--基础实战篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 Linux Capabilities 入门教程:进阶实战篇 ...

  6. 深度学习小白入门教程-基础环境篇

    深度学习小白入门教程-基础环境篇 如有图片显示失败,请回小主主页查看~ Anaconda 安装包下载方式一:官网(科学上网比较慢,不推荐) 安装包下载方式二:清华镜像(推荐) 具体安装步骤(跟着箭头来 ...

  7. 九宫怎么排列和使用_广告视频配音剪映零基础入门教程第二十三篇:剪辑之九宫格教程...

    朋友圈最火九宫格视频你们知道是怎样制作的吗?我们常常在玩朋友圈的时候想用九宫格照片,但是你们有没有遇到这种情况,想玩九宫格却发现找不到那么多能用的照片,那这时候怎么办呢?玩腻了平常图片的发法,今天我们 ...

  8. 《零基础看得懂的C++入门教程 》——(3)表达式花样挺多鸭

    一.学习目标 了解变量之间的计算 了解什么是表达式 了解什么是自增.自减 目录 预备第一篇,使用软件介绍在这一篇,C++与C使用的软件是一样的,查看这篇即可:<软件介绍> 想了解编译原理和 ...

  9. 【SQL进阶教程】第一章 case表达式

    本系列基于<SQL进阶教程>(如下图)学习,实现了书中代码及练习题代码.PS:电子书请大家各自默默脚本之家. [知识点1]case表达式概述 Case表达式有简单case表达式和搜索cas ...

最新文章

  1. 自从用完 Gradle 后,有点嫌弃 Maven 了!
  2. 关于表单的java的程序_JAVA BOT程序模拟人类用户填写表单 并 发送
  3. 几种特征选择方法的比较,孰好孰坏?
  4. 深度学习与芯片之间的羁绊往事
  5. 什么是 Delta 文件
  6. 2.登录linun 输入密码登录不进去 进入单用户模式 修改 然后reboot
  7. java监控数据库的增量_【安德鲁斯】基于脚本的数据库quot;增量更新quot;,如果不改变,每次更新java代码、!...
  8. 理解 RIPv1使用广播更新路由与RIPv2使用组播更新路由的区别
  9. Linux 中断实验
  10. c#物联网_C# 基础知识系列- 16 开发工具篇
  11. Hdu 1026 Ignatius and the Princess I
  12. Spring Security 11 种过滤器介绍
  13. vs2008 MFC工程建立
  14. Matlab图像显示
  15. 计算机控制系统编程语言,可编程控制器常用的几种编程语言
  16. linux核显显示独显内容,Linux驱动显示Intel第12代核显新特性:显示状态缓存
  17. 锂电池基本原理解析:充电及放电机制
  18. Xcode7 网络请求报错:The resource could not be loaded be
  19. vue的一些心得总结
  20. 5GCPE如何支持4G物联网卡(修改IMEI)

热门文章

  1. python time.sleep精确延时,Python time sleep()– time.sleep()方法的一站式解决方案
  2. Linux基础入门和帮助
  3. html博客图文设计,设计基本功!帮你掌握图文排版的5个小技巧—UI博客精选
  4. 【wifi测试】一周总结,新年展望(2013年1月6号更新)
  5. 计算机和人类哪个聪明相关资料,人脑和电脑哪个聪明脑筋急转弯
  6. Spring boot mybatis 打印SQL语句
  7. ERROR: Invalid HADOOP_MAPRED_HOME
  8. 几个思路教你制定性能测试方案
  9. 2.《新生——七年就是一辈子》 ——李笑来
  10. IBatis之Iterate