0
0

current_timestamp在job中不准的问题

小荷 发表于 2014年02月21日 14:04 | Hits: 2403
Tag: Working case | ..experience

有些job中跑应用程序,希望记下时间戳,但是取了current_timestamp之后,发现时间和实际的时间不准,查了几个小时。这是因为在job中跑的时候,current_timestamp是GMT格林尼治时间。

见下面的testcase,我们设置数据库服务器的时区是东八区的北京时间;客户端plsql所在的时间是东九区的首尔时间。

--create table for testing
drop table runlog_b;
CREATE TABLE runlog_b AS
SELECT SYSDATE SYS_DATE ,current_timestamp curr_timestamp,SESSIONTIMEZONE sess_timezone,current_date curr_date,
LOCALTIMESTAMP local_timestamp,SYSTIMESTAMP sys_timestamp FROM dual where 1=2;
 
 
--create procedure for testing
Create or REPLACE PROCEDURE nested_loop_b IS
BEGIN
insert into runlog_b SELECT SYSDATE,current_timestamp,SESSIONTIMEZONE,current_date,LOCALTIMESTAMP,SYSTIMESTAMP  FROM dual;
commit;
END nested_loop_b;
/
 
--在客户端plsqldev创建job,注:客户端所在的时区是+9:0,数据库服务器端的时区是北京的+8:0,可以看到如下:
SQL> SELECT SYSDATE SYS_DATE ,current_timestamp curr_timestamp,SESSIONTIMEZONE sess_timezone,current_date curr_date,
  2  LOCALTIMESTAMP local_timestamp,SYSTIMESTAMP sys_timestamp FROM dual;
 
SYS_DATE                       CURR_TIMESTAMP                                                                   SESS_TIMEZONE                                                               CURR_DATE            LOCAL_TIMESTAMP                                                                  SYS_TIMESTAMP
------------------------------ -------------------------------------------------------------------------------- --------------------------------------------------------------------------- -------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
2014/2/21 11:51:42             21-FEB-14 12.51.42.238619 PM +09:00                                              +09:00                                                                      2014/2/21 12:51:42   21-FEB-14 12.51.42.238619 PM                                                     21-FEB-14 11.51.42.238616 AM +08:00
 
SQL>
 
--创建一个job跑上面的存储过程:
 
SQL> 跑job的结果:
SYS_DATE            CURR_TIMESTAMP                           SESS_TIMEZONE        CURR_DATE           LOCAL_TIMESTAMP                SYS_TIMESTAMP
------------------- ---------------------------------------- -------------------- ------------------- ------------------------------ --------------------------------------------------
2014-02-21 11:00:49 21-FEB-14 03.00.49.010388 AM +00:00      +00:00               2014-02-21 03:00:49 21-FEB-14 03.00.49.010388 AM   21-FEB-14 11.00.49.010371 AM +08:00
2014-02-21 11:03:04 21-FEB-14 03.03.04.063177 AM +00:00      +00:00               2014-02-21 03:03:04 21-FEB-14 03.03.04.063177 AM   21-FEB-14 11.03.04.063174 AM +08:00
2014-02-21 11:06:04 21-FEB-14 03.06.04.137326 AM +00:00      +00:00               2014-02-21 03:06:04 21-FEB-14 03.06.04.137326 AM   21-FEB-14 11.06.04.137303 AM +08:00

可以看到sessiontimezone是+0:0,是格林尼治时间。

因此,如果我们要在job取时间戳,可以取systimestamp这个值。这个值是DB服务器上的时间的时间戳。

或者用加一条set time_zone也是一样的效果:

Create or REPLACE PROCEDURE nested_loop_b IS
BEGIN
execute immediate 'alter session set time_zone = ''+08:00''';
insert into runlog_b SELECT SYSDATE,current_timestamp,SESSIONTIMEZONE,current_date,LOCALTIMESTAMP,SYSTIMESTAMP  FROM dual;
commit;
END nested_loop_b;
/
 
--
SYS_DATE            CURR_TIMESTAMP                                                              SESS_TIMEZONE                  CURR_DATE                  LOCAL_TIMESTAMP                SYS_TIMESTAMP
------------------- --------------------------------------------------------------------------- ------------------------------ ------------------------------ ------------------------------ --------------------------------------------------
2014-02-21 12:03:01 21-FEB-14 12.03.01.035054 PM +08:00                                         +08:00                         2014-02-21 12:03:01        21-FEB-14 12.03.01.035054 PM   21-FEB-14 12.03.01.035051 PM +08:00
2014-02-21 12:06:01 21-FEB-14 12.06.01.108673 PM +08:00                                         +08:00                         2014-02-21 12:06:01        21-FEB-14 12.06.01.108673 PM   21-FEB-14 12.06.01.108671 PM +08:00
 
SQL>

解决方案:

  1. 在job中的存储过程用systimestamp取时间戳,而不是用current_timestamp
  2. 或者,在存储过程中先execute immediate 'alter session set time_zone = ''+08:00''';

原文链接: http://www.oracleblog.org/working-case/current_timestamp-in-job-not-correct/

0     0

我要给这篇文章打分:

可以不填写评论, 而只是打分. 如果发表评论, 你可以给的分值是-5到+5, 否则, 你只能评-1, +1两种分数. 你的评论可能需要审核.

评价列表(0)