current_timestamp在job中不准的问题

有些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”’;

发表评论

Close Menu