【问题标题】:Oracle Jobs & finding timestamp differenceOracle Jobs & 发现时间戳差异
【发布时间】:2014-01-29 21:18:53
【问题描述】:

我今天遇到了一个奇怪的问题:我有一个由作业调用的函数。我想找到从函数开始到结束的差异,然后将其记录到某个表中。

所以,假设我有函数

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 小时 + 差)。

通过愚蠢的暴力破解,我找到了解决方案:

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;

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

【问题讨论】:

    标签: oracle plsql oracle11g jobs


    【解决方案1】:

    数据库时区DBTIMEZONE和你的会话时区SESSIONTIMEZONE一样吗?

    函数SYSTIMESTAMP 返回数据类型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'
    

    【讨论】:

    • 无论如何我认为允许从另一种数据类型中减去一种数据类型是错误的,至少在这种情况下是这样。只能迷惑……
    • 嗯,这取决于编程语言的设计。在 PL/SQL 中允许隐式转换。例如,在 C# 中是不允许的,而在 VB.NET 中,您可以在编译器设置中启用或禁用它。像往常一样,拥有或不拥有它有利有弊。对于 PL/SQL,你只需要接受它。
    【解决方案2】:

    我正在使用这种方法

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

    【讨论】:

    • GET_TIME的精度为10ms,TIMESTAMP更准确,以备不时之需。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 2015-06-27
    • 2021-01-23
    • 2012-06-03
    • 1970-01-01
    • 2011-09-30
    相关资源
    最近更新 更多