暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

操作日期的函数

Oracle微学堂 2019-03-19
704

系统日期的操作

日期是很特殊的数据类型,用好了可以提高数据库的性能,而使用不当往往是错误的根源,如果你使用

字符型数据来存储日期,就放弃日期特有的计算功能。

函数 SYSDATE 求当前数据库的时间。

select sysdate from dual;

SYSDATE

---------

01-MAY-07

日期的显示格式和客户端的配置相关。

查看当前的日期显示格式

select * from nls_session_parameters where parameter='NLS_DATE_FORMAT';

PARAMETER VALUE

------------------------- ---------

NLS_DATE_FORMAT DD-MON-RR

如果你的显示是如下样子:

PARAMETER

----------------

VALUE

----------------

NLS_DATE_FORMAT

DD-MON-RR

这表示折行了,请限制 value 列的宽度

col value for a20

代表的含义是凡是列的名称是 value 的,都按照 20 个宽度来显示,你想取消该列的定义

col value clear,其中 col 是 column 的缩写。你想查看帮助 help column 即可

alter session set NLS_DATE_FORMAT='yyyy/mm/dd:hh24:mi:ss';

重新设定为我们想要的格式。

select sysdate from dual;

SYSDATE

-------------------

2007/05/01:16:32:54

查看系统时间,数据库本身没有时间,它有 scn 号,和我们的时间不同。

alter session set NLS_DATE_FORMAT='DD-MON-RR';

设定为默认的显示格式

select sysdate from dual;

再次查看,我们发现日期的显示随着客户端的格式变化而变化。

日期的内部存储都是以 yyyymmddhh24miss 存在数据库中

日期的操作函数

select round(sysdate-hiredate) days,sysdate,hiredate from emp;

 DAYS SYSDATE HIREDATE

----- ------------------- -------------------

 9632 2007/05/01:16:37:33 1980/12/17:00:00:00

 9567 2007/05/01:16:37:33 1981/02/20:00:00:00

 9565 2007/05/01:16:37:33 1981/02/22:00:00:00

 9526 2007/05/01:16:37:33 1981/04/02:00:00:00

 9347 2007/05/01:16:37:33 1981/09/28:00:00:00

 9497 2007/05/01:16:37:33 1981/05/01:00:00:00

 9458 2007/05/01:16:37:33 1981/06/09:00:00:00

 9297 2007/05/01:16:37:33 1981/11/17:00:00:00

 9367 2007/05/01:16:37:33 1981/09/08:00:00:00

 9281 2007/05/01:16:37:33 1981/12/03:00:00:00

 9281 2007/05/01:16:37:33 1981/12/03:00:00:00

 9230 2007/05/01:16:37:33 1982/01/23:00:00:00

两个日期相减的结果单位为天,往往是带小数点。我们通过函数可以取整。

SQL> select months_between(sysdate,hiredate) ,sysdate,hiredate from emp;

MONTHS_BETWEEN(SYSDATE,HIREDATE) SYSDATE HIREDATE

-------------------------------- ------------------- -------------------

 316.506237 2007/05/01:16:38:24 1980/12/17:00:00:00

 314.409462 2007/05/01:16:38:24 1981/02/20:00:00:00

 314.344946 2007/05/01:16:38:24 1981/02/22:00:00:00

 312.990108 2007/05/01:16:38:24 1981/04/02:00:00:00

 307.151398 2007/05/01:16:38:24 1981/09/28:00:00:00

 312 2007/05/01:16:38:24 1981/05/01:00:00:00

 310.764301 2007/05/01:16:38:24 1981/06/09:00:00:00

 305.506237 2007/05/01:16:38:24 1981/11/17:00:00:00

 307.796559 2007/05/01:16:38:24 1981/09/08:00:00:00

 304.957849 2007/05/01:16:38:24 1981/12/03:00:00:00

 304.957849 2007/05/01:16:38:24 1981/12/03:00:00:00

 303.312688 2007/05/01:16:38:24 1982/01/23:00:00:00

取两个日期的月间隔

select add_months(hiredate,6) ,hiredate from emp;

ADD_MONTHS(HIREDATE HIREDATE

------------------- -------------------

1981/06/17:00:00:00 1980/12/17:00:00:00

1981/08/20:00:00:00 1981/02/20:00:00:00

1981/08/22:00:00:00 1981/02/22:00:00:00

1981/10/02:00:00:00 1981/04/02:00:00:00

1982/03/28:00:00:00 1981/09/28:00:00:00

1981/11/01:00:00:00 1981/05/01:00:00:00

1981/12/09:00:00:00 1981/06/09:00:00:00

1982/05/17:00:00:00 1981/11/17:00:00:00

1982/03/08:00:00:00 1981/09/08:00:00:00

1982/06/03:00:00:00 1981/12/03:00:00:00

1982/06/03:00:00:00 1981/12/03:00:00:00

1982/07/23:00:00:00 1982/01/23:00:00:00

六个月过后是哪天。

select next_day(hiredate,'friday') ,hiredate from emp;

NEXT_DAY(HIREDATE,' HIREDATE

------------------- -------------------

1980/12/19:00:00:00 1980/12/17:00:00:00

1981/02/27:00:00:00 1981/02/20:00:00:00

1981/02/27:00:00:00 1981/02/22:00:00:00

1981/04/03:00:00:00 1981/04/02:00:00:00

1981/10/02:00:00:00 1981/09/28:00:00:00

1981/05/08:00:00:00 1981/05/01:00:00:00

1981/06/12:00:00:00 1981/06/09:00:00:00

1981/11/20:00:00:00 1981/11/17:00:00:00

1981/09/11:00:00:00 1981/09/08:00:00:00

1981/12/04:00:00:00 1981/12/03:00:00:00

1981/12/04:00:00:00 1981/12/03:00:00:00

1982/01/29:00:00:00 1982/01/23:00:00:00

当前的日期算起,下一个星期五是哪一天,这句话你可能运行失败,因为日期和客户端的字符集设置有关系,如果你是英文的客户端,就的用 Friday 来表达,日期是格式和字符集敏感的。如果你是中文的客户端,就的用‘ ’ 星期五 来表达。


select last_day(hiredate) ,hiredate from emp;

该日期的月底是哪一天。

LAST_DAY(HIREDATE) HIREDATE

------------------- -------------------

1980/12/31:00:00:00 1980/12/17:00:00:00

1981/02/28:00:00:00 1981/02/20:00:00:00

1981/02/28:00:00:00 1981/02/22:00:00:00

1981/04/30:00:00:00 1981/04/02:00:00:00

1981/09/30:00:00:00 1981/09/28:00:00:00

1981/05/31:00:00:00 1981/05/01:00:00:00

1981/06/30:00:00:00 1981/06/09:00:00:00

1981/11/30:00:00:00 1981/11/17:00:00:00

1981/09/30:00:00:00 1981/09/08:00:00:00

1981/12/31:00:00:00 1981/12/03:00:00:00

1981/12/31:00:00:00 1981/12/03:00:00:00

1982/01/31:00:00:00 1982/01/23:00:00:00

日期的进位和截取

select hiredate,round(hiredate,'mm') ,round(hiredate,'month') from emp;

select hiredate,round(hiredate,'yyyy') ,round(hiredate,'year') from emp;

select hiredate,trunc(hiredate,'mm') ,trunc(hiredate,'month') from emp;

select hiredate,trunc(hiredate,'yyyy') ,trunc(hiredate,'year') from emp;

数字的进位和截取是以小数点为中心,我们取小数点前或后的值,而日期的进位和截取是以年,月,日,时,分,秒为中心。

数据类型的隐式转换

字符串可以转化为数字和日期。数字要合法,日期要格式匹配。select ename,empno from emp where empno='7900数字和日期在赋值的时候也可以转为字符串,但在表达式的select ename,empno from emp where ename='123';select ename,empno from emp where ename=12;

数据类型的显式转换

To_char,to_date,to_number

日期转化为字符串,请说明字符串的格式。

select ename,to_char(hiredate,'yyyy/mm/dd') from emp;

ENAME TO_CHAR(HIREDATE,'YYYY/MM/DD')

-------------------- ------------------------------

SMITH 1980/12/17

ALLEN 1981/02/20

WARD 1981/02/22

JONES 1981/04/02

MARTIN 1981/09/28

BLAKE 1981/05/01

CLARK 1981/06/09

KING 1981/11/17

TURNER 1981/09/08

JAMES 1981/12/03

FORD 1981/12/03

MILLER 1982/01/23

FM 消除前置的零和空格。

select ename,to_char(hiredate,'fmyyyy/mm/dd') from emp;

ENAME TO_CHAR(HIREDATE,'FMYYYY/MM/DD

-------------------- ------------------------------

SMITH 1980/12/17

ALLEN 1981/2/20

WARD 1981/2/22

JONES 1981/4/2

MARTIN 1981/9/28

BLAKE 1981/5/1

CLARK 1981/6/9

KING 1981/11/17

TURNER 1981/9/8

JAMES 1981/12/3

FORD 1981/12/3

MILLER 1982/1/23

其他格式:year,month,mon,day,dy,am,ddsp,ddspth

格式内加入字符串请双引。

select to_char(hiredate,'fmyyyy "年" mm "月"') from emp;

SQL> col ss for a6

SQL> select sysdate,to_char(sysdate,'sssss') ss from dual;

SYSDATE SS

------------ ------

23-SEP-07 41175

当前距离零点的秒数.

SQL> select to_char(sysdate,'yyyy year mm month mon dd day dy ddsp ddspth') from

dual;

TO_CHAR(SYSDATE,'YYYYYEARMM

---------------------------------------------------------------------------------------

2007 two thousand seven 10 october oct 04 thursday thu four fourth


数字转为字符串


格式为 9,0,$,l,.

col salary for a30

SQL> select ename,to_char(sal,'9999.000') salary from emp;

ENAME SALARY

---------- --------------------

SMITH 808.000

ALLEN 1608.000

WARD 1258.000

JONES 2983.000

MARTIN 1258.000

BLAKE 2858.000

CLARK 2458.000

SCOTT 3008.000

KING 5008.000

TURNER 1508.000

ADAMS 1108.000

JAMES 958.000

FORD 3008.000

MILLER 1308.000

SQL> select ename,to_char(sal,'$00099999000.00' ) salary from emp;

ENAME SALARY

---------- --------------------

SMITH $00000000808.00

ALLEN $00000001608.00

WARD $00000001258.00

JONES $00000002983.00

MARTIN $00000001258.00

BLAKE $00000002858.00

CLARK $00000002458.00

SCOTT $00000003008.00

KING $00000005008.00

TURNER $00000001508.00

ADAMS $00000001108.00

JAMES $00000000958.00

FORD $00000003008.00

MILLER $00000001308.00


SQL> select ename,to_char(sal,'l99,999.000') salary from emp;

ENAME SALARY

---------- ------------------------------

SMITH $808.000

ALLEN $1,608.000

WARD $1,258.000

JONES $2,983.000

MARTIN $1,258.000

BLAKE $2,858.000

CLARK $2,458.000

SCOTT $3,008.000

KING $5,008.000

TURNER $1,508.000

ADAMS $1,108.000

JAMES $958.000

FORD $3,008.000

MILLER $1,308.000

SQL> select ename,TO_char(sal,'9G999D99') salary from emp;

ENAME SALARY

---------- ------------------------------

SMITH 808.00

ALLEN 1,608.00

WARD 1,258.00

JONES 2,983.00

MARTIN 1,258.00

BLAKE 2,858.00

CLARK 2,458.00

SCOTT 3,008.00

KING 5,008.00

TURNER 1,508.00

ADAMS 1,108.00

JAMES 958.00

FORD 3,008.00

MILLER 1,308.00

9 是代表有多少宽度,如果不足会显示成######,0 代表强制显示 0,但不会改变你的结果。G 是千分符,D 是小数点。

在数据库中 16 进制的表达是按照字符串来描述的,所以你想将十进制的数转换为十六进制的数使用to_char 函数。

select to_char(321,'xxxxx') from dual;

TO_CHAR(321,'XXXXX')

---------------------

 141

其中 xxxxx 的位数要足够,不然报错,你就多写几个,足够大就可以。



To_number,to_date


如果你想将十六进制的数转换为十进制的数请使用 to_number 函数。

SQL> select to_number('abc32','xxxxxxxx') from dual;

TO_NUMBER('ABC32','XXXXXXXX')

-----------------------------

 703538

SELECT TO_DATE( 'January 15, 1989, 11:00 A.M.', 'Month dd, YYYY, HH:MI A.M.',

'NLS_DATE_LANGUAGE = American') FROM DUAL; 

日期是格式和语言敏感的,切记!

select TO_NUMBER('100.00', '9G999D99') from dual;

G 为千分符,D 为小数点

RR 和 yy 日期数据类型

select to_char(sysdate,'yyyy') "当前",

to_char(to_date('98','yy'),'yyyy') "yy98",

to_char(to_date('08','yy'),'yyyy') "yy08",

to_char(to_date('98','rr'),'yyyy') "rr98",

to_char(to_date('08','rr'),'yyyy') "rr08" from dual;

结果为

2007 2098 2008 1998 2008

yy 是两位来表示年,世纪永远和说话者的当前世纪相同。

RR 比较灵活,它将世纪分为上半世纪和下半世纪。如果你处于上半世纪,描述的是 0-49,那么就和当前世纪相同,描述的是 50-99 就是上世纪。如果你处于下半世纪,描述的是 0-49,那么是下个世纪,描述的是 50-99 就是当前世纪。从而可以看出,RR 的设计完全为了 1990 年到 2010 之间我们的思维习惯而设计的。当我们时间到 2050 前后,使用起来就非常的别扭。

扫描二维码关注我的微学堂

搜索刘老师微信号:Rman-2014,备注“Oracle学习与咨询”,即可添加好友;或者扫描下面二维码,关注我的“微学堂”公众号,了解最新OCP认证动态、题库及答案解析、培训机构及讲师介绍、课堂授课内容等。每天还有一篇技术文章发布哦!



最后修改时间:2019-12-20 16:31:17
文章转载自Oracle微学堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论