Oracle 甲骨文公司;查找时间戳差异

Oracle 甲骨文公司;查找时间戳差异,oracle,plsql,oracle11g,jobs,Oracle,Plsql,Oracle11g,Jobs,我今天面临一个奇怪的问题:我有一个函数,它被job调用。我想找出从函数开始到结束的差异,然后将其记录到某个表中 假设我有一个函数 procedure p is starttime timestamp := systimestamp; procedure writeTime is diff interval day to second := systimestamp - starttime; begin -- here insert

我今天面临一个奇怪的问题:我有一个函数,它被job调用。我想找出从函数开始到结束的差异,然后将其记录到某个表中

假设我有一个函数

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;
函数中的问题是:

  • 当我手动运行它时,它运行良好,差别很明显。例如,我使用extract来解析时间间隔:
    extract(从diff开始的小时)*60*60+extract(从diff开始的分钟)*60+extract(从diff开始的秒)

  • 当我设置作业并且作业运行此函数时,我遇到了一个大问题:它返回负结果,正如我在一些测试后理解的那样,在这里生成
    systimestamp-starttime
    。似乎本次计算中的systimestamp来自格林威治时区,而我的时间要大一个小时,因此本次计算
    diff interval day to second:=systimestamp-starttime返回的值类似(-1小时+差值)

  • 通过愚蠢的暴力强迫,我找到了一个解决方案:

    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
    • 时区+1柏林
    所以现在的问题是:我真的想知道这是我的RDBMS的一个缺陷,还是我没有看到一些明显的解释为什么会这样?具体问题是:为什么在这次行动中

    starttime    timestamp := systimestamp;
    
    它需要一个时区,在此期间

    diff         interval day to second := systimestamp - starttime;
    

    在相同的会话过程中,在相同的设置下需要另一个会话?

    我正在使用这种方法

    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;
    /
    

    数据库时区是否与会话时区相同

    函数
    SYSTIMESTAMP
    返回带时区的数据类型
    时间戳
    ,因此可以隐式转换为
    时间戳
    数据类型

    LOCALTIMESTAMP
    的数据类型是
    TIMESTAMP

    试一试

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

    SELECT * FROM ALL_SCHEDULER_GLOBAL_ATTRIBUTE where attribute_name = 'DEFAULT_TIMEZONE'
    

    GET_TIME的精度是10毫秒,时间戳更精确,以防需要。无论如何,我认为允许从一种数据类型中减去另一种数据类型是错误的,至少在这种情况下是这样。它只会让人困惑……嗯,这取决于编程语言的设计。在PL/SQL中,允许隐式转换。例如,在C#中是不允许的,在VB.NET中,您可以在编译器设置中启用或禁用它。和往常一样,拥有与否也有利弊。对于PL/SQL,您只需接受它。
    starttime    timestamp := LOCALTIMESTAMP;
    
    SELECT * FROM ALL_SCHEDULER_GLOBAL_ATTRIBUTE where attribute_name = 'DEFAULT_TIMEZONE'