系统日期的操作
日期是很特殊的数据类型,用好了可以提高数据库的性能,而使用不当往往是错误的根源,如果你使用
字符型数据来存储日期,就放弃日期特有的计算功能。
函数 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认证动态、题库及答案解析、培训机构及讲师介绍、课堂授课内容等。每天还有一篇技术文章发布哦!





