【Oracle】Oracle之SQL的转换函数和条件表达式

前情提要:本篇文章将详细介绍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;
相关推荐
Lucifer三思而后行2 小时前
中国移动 BCLinux 8.8 一键安装 Oracle 26ai
数据库·oracle
djjdjdjdjjdj2 小时前
bootstrap如何修改警告框(Alert)的边框粗细
jvm·数据库·python
HalvmånEver2 小时前
MySQL的数据类型(一)
数据库·mysql
被摘下的星星2 小时前
四层模型TCP/IP协议栈
运维·服务器·网络
努力努力再努力wz2 小时前
【Linux网络系列】深入理解 I/O 多路复用:从 select 痛点到 poll 高并发服务器落地,基于 Poll、智能指针与非阻塞 I/O与线程池手写一个高性能 HTTP 服务器!(附源码)
java·linux·运维·服务器·c语言·c++·python
努力努力再努力wz2 小时前
【Linux网络系列】万字硬核解析网络层核心:IP协议到IP 分片重组、NAT技术及 RIP/OSPF 动态路由全景
java·linux·运维·服务器·数据结构·c++·python
tjc199010052 小时前
golang如何使用t.Cleanup清理测试_golang t.Cleanup测试清理使用策略
jvm·数据库·python
.千余2 小时前
【Linux】基本指令2
linux·运维·服务器
SeSs IZED2 小时前
Redis开启远程连接
数据库·redis·缓存