我今天遇到了一个奇怪的问题:我有一个由工作调用的函数。我想找到从功能开始到结束的区别,然后将其记录到某个表格。
所以,假设我有功能
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(hour from diff)*60*60 + extract(minute from diff)*60 + extract(second from 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,然后才计算差异。
我的数据库参数:
所以现在的问题是:我真的想知道它是我的RDBMS的一个错误,或者我没有看到一些明显的解释为什么会这样?具体问题是:为什么在这次行动中
starttime timestamp := systimestamp;
它需要一个时区并且在此期间
diff interval day to second := systimestamp - starttime;
在相同会话的相同过程中需要另一个具有相同设置吗?
答案 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;
/