前情提要:本篇文章将详细介绍oracle的SQL语言中的转换函数和条件表达式,并且附上对应的详细例子和SQL语句的编写以及解析。
oracle版本:19c
一、隐式和显式数据类型转换

1.1 隐式数据转换
在表达式中,Oracle服务器可以自动转换以下内容:

为了执行相关表达式,Oracle服务器可以自动转换以下内容

1.2 显示表达式转换
在 Oracle 中,CHARACTER(字符型,如 VARCHAR2)是连接数字(NUMBER)和日期(DATE)的桥梁。

二、TO_CHAR, TO_DATE, TO_NUMBER 函数
2.1 使用TO_CHAR函数转换日期
cpp
TO_CHAR(date[,'format_model'])
格式模型:
-
必须用单引号引起来
-
区分大小写
-
可以包含任何有效的日期格式元素
-
使用fm元素以删除填充的空格或抑制前导零
-
日期值之间用逗号分隔
日期格式模型的元素

| 元素 | 结果 |
|---|---|
| YYYY | 数字表示的完整年份 → 2021 |
| YEAR | 拼写出的年份(英语)→ 1984 |
| MM | 月份的两位数值 01 |
| MONTH | 月份的完整名称 5月 → MAY 10月 → October |
| MON | 月份的三字母缩写 → jan(1月) |
| DY | 星期的三字母缩写 - FRI |
| DAY | 星期的完整名称 → FRIDAY |
| DD | 月份的数字日期 01/11/31 |
- 时间元素格式化日期的时间部分:
| HH24:MI:SS AM | 15:45:32 PM |
|---|
- 通过将字符串括在双引号中来添加字符串
| HH24:MI:SS AM | 15:45:32 PM |
|---|
- 数字后缀说明数字:
| ddspth | fourteenth |
|---|
示例:使用TO_CHAR函数转换日期
- 查看默认日期格式
cpp
SQL> SELECT last_name,hire_date FROM employees WHERE department_id=100;
LAST_NAME HIRE_DATE
------------------------- ---------
Greenberg 17-AUG-02
Faviet 16-AUG-02
Chen 28-SEP-05
Sciarra 30-SEP-05
Urman 07-MAR-06
Popp 07-DEC-07
6 rows selected.
- 按照YYYY-MM-DD格式输出日期
cpp
SQL> SELECT last_name,TO_CHAR(hire_date,'YYYY-MM-DD') AS hirdate FROM employees WHERE department_id=100;
LAST_NAME HIRDATE
------------------------- ----------
Greenberg 2002-08-17
Faviet 2002-08-16
Chen 2005-09-28
Sciarra 2005-09-30
Urman 2006-03-07
Popp 2007-12-07
6 rows selected.
-- 使用fm去除日期中的前导0
-- fm是一个格式修饰符(Fill Mode)。它的主要作用是去除填充的空格和前导零。
-- 该例中fm作用于整个YYYY-MM-DD字符串,也就是说月和日的前导0都会被去掉
SQL> SELECT last_name,TO_CHAR(hire_date,'fmYYYY-MM-DD') AS hirdate FROM employees WHERE department_id=100;
LAST_NAME HIRDATE
------------------------- ----------
Greenberg 2002-8-17
Faviet 2002-8-16
Chen 2005-9-28
Sciarra 2005-9-30
Urman 2006-3-7
Popp 2007-12-7
6 rows selected.
- 按照DD MONTH YYYY格式输出日期
cpp
-- 使用fm
SQL> SELECT last_name,TO_CHAR(hire_date, 'fmDD Month YYYY') AS HIREDATE FROM employees WHERE department_id=100;
LAST_NAME HIREDATE
------------------------- --------------------------------------------
Greenberg 17 August 2002
Faviet 16 August 2002
Chen 28 September 2005
Sciarra 30 September 2005
Urman 7 March 2006
Popp 7 December 2007
6 rows selected.
-- 不使用fm
SQL> SELECT last_name,TO_CHAR(hire_date, 'DD Month YYYY') AS HIREDATE FROM employees WHERE department_id=100;
LAST_NAME HIREDATE
------------------------- --------------------------------------------
Greenberg 17 August 2002
Faviet 16 August 2002
Chen 28 September 2005
Sciarra 30 September 2005
Urman 07 March 2006
Popp 07 December 2007
6 rows selected.
2.2 将TO_CHAR函数与数字一起使用
cpp
TO_CHAR(number[, 'format_model'])
这些是一些可以与TO_CHAR函数一起使用的格式元素,用于将数字值显示为字符:

| 元素 | 结果 |
|---|---|
| 9 | 代表一个数字 |
| 0 | 强制显示零 |
| $ | 放置浮动美元符号 |
| L | 使用浮动本地货币符号 |
| . | 打印小数点 |
| , | 打印逗号作为千位指示符 |
示例:TO_CHAR转换数字输出格式
- 按照指定格式输出数字
cpp
-- 格式中是9的话就按照正常数字输出,如果是0就会在超出位数部分补0
-- 输出小数位就打小数点和
SQL> SELECT last_name,salary,TO_CHAR(salary,'99,999.99') FROM employees WHERE department_id=100;
LAST_NAME SALARY TO_CHAR(SA
------------------------- ---------- ----------
Greenberg 12008 12,008.00
Faviet 9000 9,000.00
Chen 8200 8,200.00
Sciarra 7700 7,700.00
Urman 7800 7,800.00
Popp 6900 6,900.00
6 rows selected.
-- 需要注意的是指定的格式的位数(9的个数)可以比实际位数多,但是不能比实际位数少!!!
-- 以下例子有一个人的位数比指定的位数多,就会无法输出
SQL> SELECT last_name,salary,TO_CHAR(salary,'9,999.99') FROM employees WHERE department_id=100;
LAST_NAME SALARY TO_CHAR(S
------------------------- ---------- ---------
Greenberg 12008 #########
Faviet 9000 9,000.00
Chen 8200 8,200.00
Sciarra 7700 7,700.00
Urman 7800 7,800.00
Popp 6900 6,900.00
6 rows selected.
- $和L的使用
cpp
SQL> SELECT last_name,salary,TO_CHAR(salary,'$9,999.99') FROM employees WHERE department_id=100;
LAST_NAME SALARY TO_CHAR(SA
------------------------- ---------- ----------
Greenberg 12008 ##########
Faviet 9000 $9,000.00
Chen 8200 $8,200.00
Sciarra 7700 $7,700.00
Urman 7800 $7,800.00
Popp 6900 $6,900.00
6 rows selected.
-- L可以输出当前本地系统的货币符号
-- 可以使用以下SQL来判断当前地区和货币
SQL> SELECT USERENV('LANGUAGE') FROM DUAL; -- 查看语言判断地区
USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8
SQL> SELECT * FROM V$NLS_PARAMETERS WHERE PARAMETER = 'NLS_CURRENCY'; -- 直接查看货币单位
PARAMETER
----------------------------------------------------------------
VALUE CON_ID
---------------------------------------------------------------- ----------
NLS_CURRENCY
$ 0
-- 可见当前货币单位是$,那么使用L也会输出$
SQL> SELECT last_name,salary,TO_CHAR(salary,'L99,999.99') FROM employees WHERE department_id=100;
LAST_NAME SALARY TO_CHAR(SALARY,'L99,
------------------------- ---------- --------------------
Greenberg 12008 $12,008.00
Faviet 9000 $9,000.00
Chen 8200 $8,200.00
Sciarra 7700 $7,700.00
Urman 7800 $7,800.00
Popp 6900 $6,900.00
6 rows selected.
- 以sql developer演示L
cpp
SELECT * FROM V$NLS_PARAMETERS WHERE PARAMETER = 'NLS_CURRENCY';

cpp
SELECT last_name,salary,TO_CHAR(salary,'L99,999.99') FROM employees WHERE department_id=100;

2.3 使用TO_NUMBER和TO_DATE函数
使用TO_NUMBER函数将字符串转换为数字格式:
cpp
TO_NUMBER(char[, 'format_model'])
使用TO_DATE函数将字符串转换为日期格式:
cpp
TO_DATE(char[, 'format_model'])
这些函数具有fx修饰符。 此修饰符指定TO_DATE函数的字符参数和日期格式模型的完全匹配
TO_NUMBER
TO_NUMBER函数用于将字符串类型转换为数值类型,是Oracle中常用的类型转换函数之一,与TO_CHAR()函数的作用正好相反。
需要注意的是TO_NUMBER函数中的格式是用来描述字符串的格式的,而不是用来指定字符串变成什么格式的
比如说字符串为$1234,然后格式为$9999,这是表示你的字符串格式是$符号加4位数字,然后函数就会返回4位的1234
格式与TO_CHAR一致
| 元素 | 结果 |
|---|---|
| 9 | 代表一个数字 |
| 0 | 强制显示零 |
| $ | 放置浮动美元符号 |
| L | 使用浮动本地货币符号 |
| . | 打印小数点 |
| , | 打印逗号作为千位指示符 |
cpp
-- 将字符串转换为数值
SQL> SELECT TO_NUMBER('0001234') FROM DUAL;
TO_NUMBER('0001234')
--------------------
1234
-- 需要注意的是使用0格式值时需要保证格式位数和数值位数一致,否则会报错
SQL> SELECT TO_NUMBER('1234','0000') FROM DUAL;
TO_NUMBER('1234','0000')
------------------------
1234
SQL> SELECT TO_NUMBER('1234','00000') FROM DUAL;
SELECT TO_NUMBER('1234','00000') FROM DUAL
*
ERROR at line 1:
ORA-01722: invalid number
-- 将金额字符串转化为数值
SQL> SELECT TO_NUMBER('$1234','$999999') FROM DUAL;
TO_NUMBER('$1234','$999999')
----------------------------
1234
TO_DATE
TO_DATE函数用于将字符串转换为日期类型
需要注意的是TO_DATE函数中的格式是用来描述字符串的,和TO_NUMBER一个道理
比如字符串是04/16/2026,格式是MM/DD/YYYY,这是表示字符串的前面的04代表月份,中间的16代表日期,后面的2026代表年份,最后会返回默认的日期格式
格式元素与TO_CHAR一致
| 元素 | 结果 |
|---|---|
| YYYY | 数字表示的完整年份 → 2021 |
| YEAR | 拼写出的年份(英语)→ 1984 |
| MM | 月份的两位数值 01 |
| MONTH | 月份的完整名称 5月 → MAY 10月 → October |
| MON | 月份的三字母缩写 → jan(1月) |
| DY | 星期的三字母缩写 - FRI |
| DAY | 星期的完整名称 → FRIDAY |
| DD | 月份的数字日期 01/11/31 |
cpp
SQL> SELECT TO_DATE('04/16/2026','MM/DD/YYYY') FROM DUAL;
TO_DATE('
---------
16-APR-26
三、通用函数
以下函数适用于任何数据类型,并且与使用null有关:
- NVL (expr1, expr2)
- NVL2 (expr1, expr2, expr3)
- NULLIF (expr1, expr2)
- COALESCE (expr1, expr2, ..., exprn)
3.1 NVL函数
将空值转换为实际值:
-
可以使用的数据类型是日期,字符和数字。
-
数据类型必须匹配:
-
NVL(commission_pct,0)
-
NVL(hire_date,'01-JAN-97')
-
NVL(job_id,'No Job Yet')
-
示例
cpp
-- 将为NULL的转换为指定值,对不为NULL的不做处理
SELECT last_name,commission_pct,NVL(commission_pct,0) FROM employees;

cpp
-- 计算员工一年总收入
SELECT last_name, salary, NVL(commission_pct, 0),(salary*12) + (salary*12*NVL(commission_pct, 0)) income FROM employees;

3.2 NVL2函数
cpp
NVL2(expr1,expr2,expr3)
根据expr1返回结果,若expr1不为NULL则返回expr2,若expr1为NULL则返回expr3
示例
cpp
SELECT commission_pct,NVL2(commission_pct,1,0) FROM employees;

cpp
-- 计算员工一年总收入
SELECT last_name,NVL2(commission_pct,(commission_pct+salary)*12, salary*12) income FROM employees;

3.3 NULLIF函数
cpp
NULLIF(expr1, expr2)
NULLIF函数用于比较两个表达式,若相等则返回NULL,否则返回第一个表达式的值,是SQL中处理空值和避免计算错误的重要工具。
示例
cpp
-- 当值一样转换为NULL,判断数据是否有相同值
SELECT first_name, LENGTH(first_name) "expr1",
last_name, LENGTH(last_name) "expr2",
NULLIF(LENGTH(first_name), LENGTH(last_name)) result
FROM employees;

3.4 COALESCE
COALESCE函数相对于NVL函数的优势在于,COALESCE函数可以采用多个替代值。
COALESCE函数是SQL中用于处理空值(NULL)的标准函数,它按从左到右的顺序依次检查参数,返回第一个非NULL的值,若所有参数均为NULL则返回NULL,广泛应用于空值替换、数据清洗和安全计算等场景。
cpp
SELECT COALESCE('1','2',NULL,'3'),COALESCE(NULL,'1','2',NULL),COALESCE(NULL,NULL) FROM DUAL;

示例
cpp
-- 计算工资
SELECT last_name, salary, commission_pct,
COALESCE((salary+(commission_pct*salary)), salary+2000)"New Salary"
FROM employees;

四、条件表达式
在SQL语句中提供IF-THEN-ELSE逻辑的使用
使用以下方法:
-
CASE 表达式
-
DECODE 函数
4.1 CASE表达式
通过执行IF-THEN-ELSE语句来促进有条件的查询
cpp
CASE expr WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
WHEN comparison_exprn THEN return_exprn
ELSE else_expr]
END
示例
cpp
SELECT last_name, job_id, salary,
CASE job_id WHEN 'IT_PROG' THEN 1.10*salary
WHEN 'ST_CLERK' THEN 1.15*salary
WHEN 'SA_REP' THEN 1.20*salary
ELSE salary END "REVISED_SALARY"
FROM employees;

- 需要注意的是CASE表达式是自上到下匹配,如果匹配到则返回结果并且不会再进行后续的匹配了
cpp
-- 对工资进行分级
SELECT last_name,salary,
CASE WHEN salary < 5000 THEN 'Low'
WHEN salary < 10000 THEN 'Medium'
WHEN salary < 20000 THEN 'Good'
ELSE 'Excellent'
END qualified_salary
FROM employees;

cpp
-- 上面的例子使用的CASE表达式判断是正常的顺序,如果将顺序调换就达不到上面的效果
SELECT last_name,salary,
(CASE WHEN salary < 20000 THEN 'Good'
WHEN salary < 10000 THEN 'Medium'
WHEN salary < 5000 THEN 'Low'
ELSE 'Excellent'
END) qualified_salary
FROM employees;
-- 这里将good和low的判断条件顺序调换
-- 可见CASE是匹配到结果后就退出,所以在使用时需要注意判断条件的顺序是否合理

4.2 DECODE函数
DECODE函数是Oracle数据库特有的条件判断工具,通过简洁的等值匹配语法实现IF-THEN-ELSE逻辑,特别适合处理简单等值转换和数据映射,但在非Oracle环境中通常需要转换为CASE表达式。
cpp
DECODE(col|expression, search1, result1
[, search2, result2,...,]
[, default])
col|expression:列或者要比较的资源值
search:与col|expression比较的目标值
result:匹配时返回的替换值
default:可选参数,无匹配时返回的默认值
示例
cpp
-- 判断工资/2000后的整数位
SELECT last_name, salary,
DECODE (TRUNC(salary/2000, 0),
0, 0.00,
1, 0.09,
2, 0.20,
3, 0.30,
4, 0.40,
5, 0.42,
6, 0.44,
0.45) TAX_RATE
FROM employees
WHERE department_id = 80;

cpp
-- 根据工作计算工资
SELECT last_name, job_id, salary,
DECODE(job_id, 'IT_PROG', 1.10*salary,
'ST_CLERK', 1.15*salary,
'SA_REP', 1.20*salary,
salary) REVISED_SALARY
FROM employees;
