SYSDATE是我们在Oracle开发中经常要用到的一种单行函数(single row function),该函数用以返回当前的日期与时间,常和DUAL伪表一起合作。SYSDATE实际上指的是SYSDATE()函数,但是因为这个函数没有参量,所以这里可以省略()圆括号。另外SYSDATE函数是用于获取数据库所在的操作系统的当前时间值的,所以它和数据库或会话的时区没有关系。 我们可以使用NLS_DATE_FORMAT参数或者TO_CHAR函数来获得我们想要的SYSDATE日期格式,具体的格式代码如下:
Format Code |
Explanation |
YEAR |
Year, spelled out |
YYYY |
4-digit year |
MM |
Month (01-12; JAN = 01). |
MON |
Abbreviated name of month. |
MONTH |
Name of month, padded with blanks to length of 9 characters. |
D |
Day of week (1-7). |
DAY |
Name of day. |
DD |
Day of month (1-31). |
DDD |
Day of year (1-366). |
DY |
Abbreviated name of day. |
HH |
Hour of day (1-12). |
HH12 |
Hour of day (1-12). |
HH24 |
Hour of day (0-23). |
MI |
Minute (0-59). |
SS |
Second (0-59). |
SSSSS |
Seconds past midnight (0-86399). |
具体的用法如:
syntax:
select to_char(sysdate,'FORMAT CODES') from dual;
select to_char(sysdate,'YEAR-MON-DAY HH24:MI:SS') from dual;
TO_CHAR(SYSDATE,'YEAR-MON-DAY HH24:MI:SS')
--------------------------------------------------------------------------------
TWENTY ELEVEN-AUG-WEDNESDAY 21:34:43
与SYSDATE不同,CURRENT_DATE()函数会返回数据库会话所设置的本地时区的当前日期。 我们来具体看一下这2个函数所返回结果的差异:
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
SQL> select * from global_name;
GLOBAL_NAME
--------------------------------------------------------------------------------
www.oracledatabase12g.com
SQL> alter session set nls_date_format='YYYY-MM-DD HH24:mi:ss';
Session altered.
SQL> set linesize 200 pagesize 1400;
SQL> col sessiontimezone for a20
SQL> select current_date, sysdate,dbtimezone,sessiontimezone from dual;
CURRENT_DATE SYSDATE DBTIME SESSIONTIMEZONE
------------------- ------------------- ------ --------------------
2011-08-24 19:53:09 2011-08-24 19:53:09 +08:00 +08:00
/* 我们调整session的所在时区到+09:00 */
SQL> alter session set time_zone='+09:00';
Session altered.
SQL> select current_date, sysdate,dbtimezone,sessiontimezone from dual;
CURRENT_DATE SYSDATE DBTIME SESSIONTIMEZONE
------------------- ------------------- ------ --------------------
2011-08-24 20:56:33 2011-08-24 19:56:33 +08:00 +09:00
/* 可以看到current_date所返回的时间增长了一个小时,而SYSDATE不变 */
另外请注意SYSDATE函数的类型并非是DATE类型,而是其特有的类型:
SQL> create table mytime(t1 date);
Table created.
SQL> insert into mytime values (sysdate);
1 row created.
SQL> commit;
Commit complete.
SQL> select dump(t1), dump(sysdate), dump( current_date) from mytime;
DUMP(T1)
--------------------------------------------------------------------------------
DUMP(SYSDATE)
--------------------------------------------------------------------------------
DUMP(CURRENT_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 120,111,8,24,21,31,59
Typ=13 Len=8: 219,7,8,24,20,32,12,0
Typ=13 Len=8: 219,7,8,24,20,32,12,0
以上可以看到sysdate和current_date都属于TYPE=13,而普通DATE类型为TYPE=12
数据类型type=12代表DATE Valid date range from January 1, 4712 BC to December 31, 9999 AD. 因为sysdate的时钟取自操作系统,所以DBA同样需要关心操作系统本身时区的设置。不当的时区设置可能导致数据库内部的定时作业系统紊乱,主要会影响使用DBMS_JOB调用的一些JOB,DBMS_JOB包不会考虑到时区的因素,而仅仅考虑sydate的值(DBMS_JOB uses the "date" datatype to store the start date/time and does not store/use timezone related information. JOBS who are scheduled are always executed when sysdate => next execution time. )。如果使用DBMS_SCHEDULER则会考虑具体的时区。 此外一些使用夏令时的地区还会面临更复杂的DST问题,详细可以参考ORAganism的文章 <Fake lack of TimeZones in DBMS_JOBs>和MOS文档 <DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained. [ID 467722.1]> & <Troubleshooting DBMS_SCHEDULER and DBMS_JOB [ID 783357.1] >:
DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained. [ID 467722.1]
Applies to:
Oracle Server - Enterprise Edition - Version: 9.0.1.0 to 11.2.0.2 - Release: 9.0.1 to 11.2
Information in this document applies to any platform.
Purpose
This note gives a overview of how DBMS_SCHEDULER / DBMS_JOB react on DST transitions and what
to know when using timezone information with jobs.
Scope and Application
To be used when DBMS_SCHEDULER jobs run at a wrong time after a DST change or you have output
from jobs selecting from TIMESTAMP WITH LOCAL TIMEZONE columns that is not correct.
If things about timezones are not clear please have first a look at Note 340512.1 Timestamps
& time zones - Frequently Asked Questions.
DBMS_SCHEDULER or DBMS_JOB And DST / Timezones Explained.
When running trough DBMS_SCHEDULER or DBMS_JOB a job output using TIMESTAMP WITH LOCAL
TIMEZONE gives the wrong time.This happens when you use DBMS_SCHEDULER or DBMS_JOB to run jobs
who select information from TIMESTAMP WITH LOCAL TIMEZONE fields.
The time in a TIMESTAMP WITH LOCAL TIMEZONE that will be returned depends on the SESSIONTIMEZONE.
select sessiontimezone from dual;
If a TIMESTAMP WITH LOCAL TIMEZONE field contains for example "20-DEC-2007 15:15 -08:00" and
your session timezone is also -08:00 you will see 15:15.
If you change the session timezone to (for example) -07:00 then you will see 16:15,
witch is normal and intended.
Jobs using DBMS_SCHEDULER and DBMS_JOB however use a SESSIONTIMEZONE set to UTC (= +00:00 ).
Hence, above example will give 15 + 8 = 23:15 when selected trough a job.
If you use jobs that provide TIMESTAMP WITH LOCAL TIMEZONE then you may need to
included in the job an alter session to change the SESSIONTIMEZONE.
execute immediate 'alter session set time_zone = ''-08:00''';
If you want the job to follow DST rules then you need to use a named timezone that
follows the DST rules you want to use:
execute immediate 'alter session set time_zone = ''US/Pacific''';
There is Enhancement Request 5479680 - INCORPORATE SESSIONTIMEZONE INFORMATION INTO
JOB INFORMATION to a) use the session timezone of the submitting session as timezone and b)
have a way to see with what timezone a job is submitted.
Job runtime time after DST has changed.
When using DBMS_JOB:
DBMS_JOB uses the "date" datatype to store the start date/time and does not store/use timezone