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]

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

simple case
首先计算 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 表达式的语法如下:

WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... [ELSE default_result]

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

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

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

SELECT emp_name AS "员工姓名",
         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 "学科名称",
         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 表达式如下:

WHEN expr1 IS NOT NULL THEN expr1 WHEN expr2 IS NOT NULL THEN expr2 WHEN expr3 IS NOT NULL THEN expr3 ...
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 表达式进行表示:

WHEN expr1 = expr2 THEN NULL ELSE expr1

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 中的 CASE 表达式可以根据不同条件产生不同的结果,实现类似于编程语言中的 IF-THEN-ELSE 逻辑功能。例如,根据员工的 KPI 计算相应的涨薪幅度,根据考试成绩评出优秀、良好、及格等。COALESCE 和 NULLIF 函数是两个简写形式的 CASE 表达式。另外,Oracle 还提供了专有的 NVL、NVL2 以及 DECODE 函数。
MySQL中 CASE 表达式的介绍及使用MySQL CASE表达式MySQL CASE 表达式介绍简单 ==CASE== 表达式(simple case expression)搜索 ==CASE== (Searched CASE expression) MySQL CASE表达式 简介: 使用MySQL CASE 表达式向查询中添加if-else逻辑。 MySQL CASE 表达式介绍 MySQL case 表达式是一种控制流结构,允许你向查询条件中添加if-else逻辑。一般来说,你可以使用 case
1.1 数据库的几个重要概念 数据(data):是指所有能输入到计算机中并被计算机程序处理的符号的总称,一个数据库可以管理多种数据。 数据库(database):是指以一定方式存储在一起,能为多个用户共享,具有尽可能小的数据冗余特点,能与程序彼此独立的数据集合。一个数据库管理系统可以管理多个database。 数据库管理系统(DBMS):是一种管理数据库的软件。在o... (1)CASE表达式可以让你可以在SQL中使用类似于if… then…else的逻辑而不需要调用程序 (2)一个简单的CASE表达式Oracle将会搜索第一对when…then来与表达式做匹配,如果匹配了则返回表达式的值。如果没有任何一个when…then符合条件,将会执行 ELSE后面的语句,oracle将会返回else表达式的值。否则,oracle将会返回