Oracle常用函数集锦

1.空值处理函数

1.1 nvl

用途:将第一参数(可能的)空值转换为第二参数

典型应用场景:A表左联到B表,如果某字段可能为空时。

 例:

复制代码
SQL> select emp.name,nvl(dept.name,'梁山') as DEPT from emp
  2  left join dept
  3  on emp.dept_id=dept.id;

NAME                 DEPT
-------------------- --------------------
鲁智深               二龙山
武松                 二龙山
花荣                 清风寨
周通                 桃花山
李逵                 梁山
复制代码

建表充值:

复制代码
create table emp(
    name varchar2(20),
    dept_id number(6)
);

insert into emp(name,dept_id) values('鲁智深',1);
insert into emp(name,dept_id) values('武松',1);
insert into emp(name,dept_id) values('花荣',2);
insert into emp(name,dept_id) values('李逵',4);
insert into emp(name,dept_id) values('周通',3);

create table dept(
   id number(6),
   name varchar2(20)
);

insert into dept(id,name) values(1,'二龙山');
insert into dept(id,name) values(2,'清风寨');
insert into dept(id,name) values(3,'桃花山');
复制代码

解析:李逵的dept_id=4在dept表里是没有值的,对于这种情况便统一处理为‘梁山’。 

 

1.2 nvl2

改函数是对nvl的扩展,它有三个参数,当第一参数不为空是取第二参数,为空时取第三参数。

示例:

复制代码
select nvl2(b.status,'Failed','Succeeded') as sts
from 
(
    select decode(a.stat,0,null,1,'s') as status
    from
    (  select mod(level,2) as stat
       from dual
       connect by level<5
    ) a
) b
复制代码

执行结果:

复制代码
luna@ORCL>select nvl2(b.status,'Failed','Succeeded') as sts
  2  from
  3  (
  4      select decode(a.stat,0,null,1,'s') as status
  5      from
  6      (  select mod(level,2) as stat
  7         from dual
  8         connect by level<5
  9      ) a
 10  ) b;

STS
---------
Failed
Succeeded
Failed
Succeeded
复制代码

 

1.3 nullif 比较两参数值,相等返回空,不相等返回第一参数值 (此函数相对少见)

示例:

复制代码
luna@ORCL>select nullif(5/2,2) from dual;

NULLIF(5/2,2)
-------------
          2.5

已选择 1 行。

luna@ORCL>select nullif(5/2,2.5) from dual;

NULLIF(5/2,2.5)
---------------


已选择 1 行。
复制代码

 

1.4 coalesce 取多个参数中第一个不为空的值

比如有这样一张表:

create table emp826(
    name nvarchar2(20),
    hire_date timestamp,
    update_date timestamp,
    create_date timestamp);

这样充值:

insert into emp826(name,hire_date,update_date,create_date) 
values('newton',to_date('2022-01-01','yyyy-MM-dd'),to_date('2022-04-01','yyyy-MM-dd'),to_date('2022-08-01','yyyy-MM-dd'));

insert into emp826(name,hire_date,update_date,create_date) 
values('gause',null,to_date('2022-04-01','yyyy-MM-dd'),to_date('2022-08-01','yyyy-MM-dd'));

insert into emp826(name,hire_date,update_date,create_date) 
values('einstain',null,null,to_date('2022-08-01','yyyy-MM-dd'));

可以看到,有人的hire_date是空,这时该取update_date;有人的update_date还是空,这时该取create_date.

用coalesce就可以实现这个逻辑:

SQL:

select name,to_char(coalesce(hire_date,update_date,create_date),'yyyy-MM-dd') as hdate from emp826;

执行效果:

luna@ORCL>select name,to_char(coalesce(hire_date,update_date,create_date),'yyyy-MM-dd') as hdate from emp826;

NAME                                     HDATE
---------------------------------------- ----------
newton                                   2022-01-01
gause                                    2022-04-01
einstain                                 2022-08-01

 

2.分支函数

2.1 decode

语法:decode(列,匹配内容1,显示值1,匹配内容2,显示值2,...,匹配内容N,显示值N,全不匹配时的显示值);

这个函数在分支数少而简单时可以替代case when

复制代码
luna@ORCL>select decode(trunc(dbms_random.value(1,6)),1,'waiting',2,'runnable',3,'running',4,'failed',5,'interrupted',6,'succeeded','unclassified') from dual;

DECODE(TRUNC
------------
interrupted

已选择 1 行。

luna@ORCL>select decode(trunc(dbms_random.value(1,6)),1,'waiting',2,'runnable',3,'running',4,'failed',5,'interrupted',6,'succeeded','unclassified') from dual;

DECODE(TRUNC
------------
runnable

已选择 1 行。
复制代码

 

2.2 case when

示例:下面SQL将1,2,3三种状态转化为对应的running、failed、succeeded。

复制代码
luna@ORCL>select case when a.val=1 then 'running' when a.val=2 then 'failed' else 'succeeded' end as status
  2  from
  3  (select trunc(dbms_random.value(1,3)) as val from dual) a;

STATUS
---------
running

已选择 1 行。
复制代码

此例中case when可以被decode取代,但对于复杂判断还是case when更顺手些。如

select
    tb.task_id,
    decode(tc.alls_flg,null,0,1) as sum,
    decode(tb.alls_flg,tc.alls_flg,1,0) as succeeded,
    case when tc.alls_flag is null then 0 when tb.alls_flg=tc.alls_flg then 0 else 1 end as fialed
from tb
left join tc
on tb.job_ids=tc.job_ids

 

3.转换函数

3.1 to_char

示例:比如将timestamp类型数据转化成我们熟悉的年月日时分秒格式

luna@ORCL>select to_char(sysdate,'yyyy-MM-dd hh:mi:ss') as time from dual;

TIME
-------------------
2022-08-26 02:54:03

 还可以来一个比较特别的例子:

luna@ORCL>select to_char(sysdate,'fmDdspth / Month Year fmHH:MI:SS') from dual;

TO_CHAR(SYSDATE,'FMDDSPTH/MONTHYEARFMHH:MI:SS')
---------------------------------------------------------------------------
Twenty-Sixth / 8月 Twenty Twenty-Two 04:38:31

已选择 1 行。

to_char还可以将数字转化为货币格式,比如有这样一张表:

create table sal0826(
     year  number(4),
     total number(12)
);

其数据是:

insert into sal0826(year,total) values('2021','254000');
insert into sal0826(year,total) values('2022','286000');
insert into sal0826(year,total) values('2023','360000');

将其转化为美元可以这样做:

luna@ORCL>select year,to_char(total,'$999,999.00') as annual_salary from sal0826;

      YEAR ANNUAL_SALAR
---------- ------------
      2021  $254,000.00
      2022  $286,000.00
      2023  $360,000.00

或是人民币格式可以是:

luna@ORCL>select year,to_char(total,'L999,999.00') as annual_salary from sal0826;

      YEAR ANNUAL_SALARY
---------- ---------------------
      2021254,000.00
      2022286,000.00
      2023360,000.00

中国喜欢以万为单位,那么改变一下逗号位置即可:

复制代码
luna@ORCL>select year,to_char(total,'L99,9999.00') as annual_salary from sal0826;

      YEAR ANNUAL_SALARY
---------- ---------------------
      202125,4000.00
      202228,6000.00
      202336,0000.00

已选择3行。
复制代码

 用于计算一天前,一周前,一月前,一年前的日期可以这样做:

select
    to_char((sysdate-interval'1'day),'yyyy-mm-dd') as yesterday,
    to_char((sysdate-interval'7'day),'yyyy-mm-dd') as weekago,
    to_char((sysdate-interval'1'month),'yyyy-mm-dd') as monthago,
    to_char((sysdate-interval'1'year),'yyyy-mm-dd') as yearago
from dual

执行效果:

复制代码
SQL> select
  2      to_char((sysdate-interval'1'day),'yyyy-mm-dd') as yesterday,
  3      to_char((sysdate-interval'7'day),'yyyy-mm-dd') as weekago,
  4      to_char((sysdate-interval'1'month),'yyyy-mm-dd') as monthago,
  5      to_char((sysdate-interval'1'year),'yyyy-mm-dd') as yearago
  6  from dual;

YESTERDAY            WEEKAGO              MONTHAGO
-------------------- -------------------- --------------------
YEARAGO
--------------------
2022-08-27           2022-08-21           2022-07-28
2021-08-28
复制代码

 

3.2 to_date

示例:将字符串形式的建国日转化为timestamp形式。

luna@ORCL>select to_date('1949-10-1','yyyy-MM-dd') as national_day from dual;

NATIONAL_DAY
--------------
01-10月-49

 利用to_date还可以得知两个日期间的天数:

select trunc(to_date('2022-09-05','yyyy-mm-dd')-to_date('2022-09-01','yyyy-mm-dd'))+1 from dual;

执行:

SQL> select trunc(to_date('2022-09-05','yyyy-mm-dd')-to_date('2022-09-01','yyyy-mm-dd'))+1 from dual;

TRUNC(TO_DATE('2022-09-05','YYYY-MM-DD')-TO_DATE('2022-09-01','YYYY-MM-DD'))+1
------------------------------------------------------------------------------
                                                                             5

辅之以connect by,可以得到两个日期间隔间的连续日期:

select to_char(to_date('2018-09-01', 'yyyy-mm-dd') + ROWNUM - 1, 'yyyy-mm-dd') as dt
from dual
connect by rownum<=trunc(to_date('2022-09-05','yyyy-mm-dd')-to_date('2022-09-01','yyyy-mm-dd'))+1

执行:

复制代码
SQL> select to_char(to_date('2018-09-01', 'yyyy-mm-dd') + ROWNUM - 1, 'yyyy-mm-dd') as dt
  2  from dual
  3  connect by rownum<=trunc(to_date('2022-09-05','yyyy-mm-dd')-to_date('2022-09-01','yyyy-mm-dd'))+1;

DT
--------------------
2018-09-01
2018-09-02
2018-09-03
2018-09-04
2018-09-05
复制代码

 

3.3 to_number

 将字符串变成数字,如:

luna@ORCL>select to_number('1.25')*4 from dual;

TO_NUMBER('1.25')*4
-------------------
                  5

还可以将特定格式字符串还原成数字

luna@ORCL>select TO_NUMBER('$123,456.78','$999999.99') from dual;

TO_NUMBER('$123,456.78','$999999.99')
-------------------------------------
                            123456.78

已选择 1 行。

还可以将十六进制数转化为十进制

luna@ORCL>select to_number('AF','XX') from dual;

TO_NUMBER('AF','XX')
--------------------
                 175

 to_number和to_char的组合对取日期的一部分有奇效,如:

SQL:

复制代码
select 
    to_number(to_char(sysdate,'hh24')) as hour,   --小时
    to_number(to_char(sysdate,'mi'))   as minute, --
    to_number(to_char(sysdate,'ss'))   as second, --
    to_number(to_char(sysdate,'dd'))   as dday,   --
    to_number(to_char(sysdate,'mm'))   as month,  --
    to_number(to_char(sysdate,'yyyy')) as year,   --
    to_number(to_char(sysdate,'ddd'))  as nday    --年内第几天
from dual
复制代码

执行效果:

复制代码
SQL> select
  2      to_number(to_char(sysdate,'hh24')) as hour,   --小时
  3      to_number(to_char(sysdate,'mi'))   as minute, --
  4      to_number(to_char(sysdate,'ss'))   as second, --
  5      to_number(to_char(sysdate,'dd'))   as dday,   --
  6      to_number(to_char(sysdate,'mm'))   as month,  --
  7      to_number(to_char(sysdate,'yyyy')) as year,   --
  8      to_number(to_char(sysdate,'ddd'))  as nday    --年内第几天
  9  from dual;

      HOUR     MINUTE     SECOND       DDAY      MONTH       YEAR       NDAY
---------- ---------- ---------- ---------- ---------- ---------- ----------
        22         45         16         26          8       2022        238
复制代码

 如果要判断字段是由数字组成可以使用正则表达式函数 regexp_like(column,'^[0-9]+$')

比如有这样一张表:

create table emp827(
    name nvarchar2(20),
    sn varchar2(20)
);

这样充值:

insert into emp827(name,sn) values('Andy','9527');
insert into emp827(name,sn) values('Bill','9528');
insert into emp827(name,sn) values('Cindy','a123');
insert into emp827(name,sn) values('Douglas','34.56');

使用regexp_like的语句为:

select * from emp827 where regexp_like(sn,'^[0-9]+$');

执行效果是:

SQL> select * from emp827 where regexp_like(sn,'^[0-9]+$');

NAME                 SN
-------------------- --------------------
Andy                 9527
Bill                 9528

 

4.日期函数

4.1 months_between 用于计算两个timestamp之间的月数

示例:取当前日期和120天前的日期的月份差值

luna@ORCL>select months_between(sysdate,sysdate-120) from dual;

MONTHS_BETWEEN(SYSDATE,SYSDATE-120)
-----------------------------------
                         3.93548387

 

4.2 add_months 在timestamp上进行月份添加

示例:在timestamp上加一天直接+1即可,如果要增加一个月可以用add_months,它能省去判断大小月闰月的麻烦。

复制代码
luna@ORCL>select to_char(sysdate+1,'yyyy-MM-dd') from dual;

TO_CHAR(SY
----------
2022-08-27

luna@ORCL>select to_char(add_months(sysdate,1),'yyyy-MM-dd') from dual;

TO_CHAR(AD
----------
2022-09-26
复制代码

 

4.3 next_day 返回指定日期的下一个星期几

示例:今天是2022-08-26,如下SQL能显示下周一是2022-08-29。注意第二参数是1~7,代表周日、周一到周六

luna@ORCL>select to_char(next_day(sysdate,2),'yyyy-MM-dd') from dual;

TO_CHAR(NE
----------
2022-08-29

  

4.4 last_day 返回指定日期所在月份的最后一天

示例:今天是2022-08-26,如下SQL能显示本月最后一天是2022-08-31

luna@ORCL>select to_char(last_day(sysdate),'yyyy-MM-dd') from dual;

TO_CHAR(LA
----------
2022-08-31

示例:今天是2022-08-26,如下SQL能显示距月底还有多少天(等于计算距离发工资日还有多少天)

luna@ORCL>select last_day(sysdate)-sysdate as leftDays from dual;

  LEFTDAYS
----------
         5

 

4.5 trunc  将指定日期截取到年或月或日

示例:取当前日期所在月份的第一天。

luna@ORCL>select to_char(trunc(sysdate,'month'),'yyyy-MM-dd') as firstday from dual;

FIRSTDAY
----------
2022-08-01

示例:取当前日期所在年份的第一天

luna@ORCL>select to_char(trunc(sysdate,'year'),'yyyy-MM-dd') as firstday from dual;

FIRSTDAY
----------
2022-01-01

示例:计算22年圣诞节离当前日期2022-08-26还有多少天

luna@ORCL>select trunc(to_date('2022-12-25','yyyy-MM-dd')-sysdate) as days from dual;

      DAYS
----------
       120

示例:取今天是本月的第几天,即取日期中的日子 ,比如今日是2022-08-26,想要得到26这个值

luna@ORCL>select trunc(sysdate-trunc(sysdate,'month'))+1 as day from dual;

       DAY
----------
        26

已选择 1 行。

 

4.6 extract 从date或是timestamp字段中抽取出特定值。

如:

select 
    extract(year from sysdate) as year,
    extract(month from sysdate) as month,
    extract(day from sysdate) as day
from dual;

执行效果: 

复制代码
SQL> select
  2      extract(year from sysdate) as year,
  3      extract(month from sysdate) as month,
  4      extract(day from sysdate) as day
  5  from dual;

      YEAR      MONTH        DAY
---------- ---------- ----------
      2022          8         27
复制代码

 又如:

select 
    extract(year   from timestamp'2022-08-27 14:25:25') as year,
    extract(month  from timestamp'2022-08-27 14:25:25')  as month,
    extract(day    from timestamp'2022-08-27 14:25:25')  as day,
    extract(hour   from timestamp'2022-08-27 14:25:25')  as hour,
    extract(minute from timestamp'2022-08-27 14:25:25')  as minute,
    extract(second from timestamp'2022-08-27 14:25:25')  as second
from dual;

执行效果: 

复制代码
SQL> select
  2      extract(year   from timestamp'2022-08-27 14:25:25') as year,
  3      extract(month  from timestamp'2022-08-27 14:25:25')  as month,
  4      extract(day    from timestamp'2022-08-27 14:25:25')  as day,
  5      extract(hour   from timestamp'2022-08-27 14:25:25')  as hour,
  6      extract(minute from timestamp'2022-08-27 14:25:25')  as minute,
  7      extract(second from timestamp'2022-08-27 14:25:25')  as second
  8  from dual;

      YEAR      MONTH        DAY       HOUR     MINUTE     SECOND
---------- ---------- ---------- ---------- ---------- ----------
      2022          8         27         14         25         25
复制代码

 这个函数还可以告诉我们两个timestamp差值之间间隔了多少天。

SQL:

select 
    extract(day from a.dt) as day
from 
(
    select (timestamp'2022-08-28 08:30:00'-timestamp'2021-09-13 08:30:00') as dt from dual
)   a

执行:

复制代码
SQL> select
  2      extract(day from a.dt) as day
  3  from
  4  (
  5      select (timestamp'2022-08-28 08:30:00'-timestamp'2021-09-13 08:30:00') as dt from dual
  6  )   a;

       DAY
----------
       349
复制代码

这个用于计算高考中考倒计时,距XX纪念日有N天这样的例子很方便。

 

5.数学函数

5.1 round 对小数点后的数字进行四舍五入

示例:对2.5进行四舍五入

luna@ORCL>select round(5/2) from dual;

ROUND(5/2)
----------
         3

示例:对1.25进行四舍五入

luna@ORCL>select round(5/4) from dual;

ROUND(5/4)
----------
         1

 示例:将圆周率四舍五入到第四位

luna@ORCL>select round(3.14159,4) from dual;

ROUND(3.14159,4)
----------------
          3.1416

 

5.2 trunc 截断小数点后的数字

示例:对2.5进行截断

luna@ORCL>select trunc(5/2) from dual;

TRUNC(5/2)
----------
         2

示例:对1.25进行截断

luna@ORCL>select trunc(5/4) from dual;

TRUNC(5/4)
----------
         1

示例:对圆周率第四位后舍弃 

luna@ORCL>select trunc(3.14159,4) from dual;

TRUNC(3.14159,4)
----------------
          3.1415

 

5.3 mod 取余数

示例:求10 % 3

luna@ORCL>select mod(10,3) from dual;

 MOD(10,3)
----------
         1

 

6.字符函数

6.1 lower/upper/initcap 小写化、大写化、首字母大写化

luna@ORCL>select lower('albert'),upper('albert'),initcap('albert') from dual;

LOWER( UPPER( INITCA
------ ------ ------
albert ALBERT Albert

6.2 length 取字符串长度

luna@ORCL>select length('albert') from dual;

LENGTH('ALBERT')
----------------
               6

6.2 instr 子串位置查找

复制代码
luna@ORCL>select instr('albert','er') from dual;

INSTR('ALBERT','ER')
--------------------
                   4

已选择 1 行。

luna@ORCL>select instr('albert','e') from dual;

INSTR('ALBERT','E')
-------------------
                  4

已选择 1 行。
复制代码

 

持续更新中.

posted @   逆火狂飙  阅读(506)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
历史上的今天:
2019-08-16 【高中数学/函数/零点】求分段函数f(x)=x^2-4x+2(x>=1) f(x)=|lg(1-x)| (x<1)的零点个数
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东
点击右上角即可分享
微信分享提示