Oracle Jobs&找时间戳差异

时间:2014-01-29 11:42:55

标签: oracle plsql oracle11g jobs

我今天遇到了一个奇怪的问题:我有一个由工作调用的函数。我想找到从功能开始到结束的区别,然后将其记录到某个表格。

所以,假设我有功能

procedure p is
  starttime    timestamp := systimestamp;

  procedure writeTime
    is
      diff         interval day to second := systimestamp - starttime;
  begin
    -- here insert diff to some table
  end;
begin
  -- doing some long stuff

  writeTime();
exception
  when others then
    writeTime();
end;

该功能的问题是:

  1. 当我手动运行时,效果很好,区别很明显。例如。我使用 extract 来解析间隔:extract(hour from diff)*60*60 + extract(minute from diff)*60 + extract(second from diff)

  2. 当我设置作业并且作业运行此函数时,我遇到了一个很大的问题:它返回负面结果,正如我在经过一些测试后所知,这里生成了systimestamp - starttime。看起来像这个计算中的systimestamp来自格林威治时区,而我的大一小时,所以这个计算diff interval day to second := systimestamp - starttime;返回的值就像(-1小时+差异)。

  3. 通过愚蠢的暴力迫使我找到了解决方案:

    procedure p is
      starttime    timestamp := systimestamp;
    
      procedure writeTime
        is
          diff         interval day to second;
          endtime      timestamp := systimestamp;
      begin
        diff := endtime - starttime;
    
        -- here insert diff to some table
      end;
    begin
      -- doing some long stuff
    
      writeTime();
    exception
      when others then
        writeTime();
    end;
    

    它首先只是在变量中写入systimestamp,然后才计算差异。

    我的数据库参数:

    • Oracle 11.2.0.2.0
    • Timezone +1 Berlin

    所以现在的问题是:我真的想知道它是我的RDBMS的一个错误,或者我没有看到一些明显的解释为什么会这样?具体问题是:为什么在这次行动中

    starttime    timestamp := systimestamp;
    

    它需要一个时区并且在此期间

    diff         interval day to second := systimestamp - starttime;
    

    在相同会话的相同过程中需要另一个具有相同设置吗?

2 个答案:

答案 0 :(得分:2)

数据库时区DBTIMEZONE与会话时区SESSIONTIMEZONE相同吗?

函数SYSTIMESTAMP返回datatye TIMESTAMP WITH TIME ZONE,因此您隐式转换为TIMESTAMP数据类型。

LOCALTIMESTAMP的数据类型为TIMESTAMP

尝试

starttime    timestamp WITH TIME ZONE := systimestamp;

starttime    timestamp := LOCALTIMESTAMP;

您可以使用此查询检查计划作业正在运行的时区:

SELECT * FROM ALL_SCHEDULER_GLOBAL_ATTRIBUTE where attribute_name = 'DEFAULT_TIMEZONE'

答案 1 :(得分:0)

我正在使用这种方法

declare
 time_start number;
begin 
 time_start := dbms_utility.get_time();

 -- some heavy lifting 

 dbms_output.put_line(dbms_utility.get_time() - time_start);
end;
/