Question

I've faced today a weird problem: I have a function which is called by job. I want to find the difference from start of the function till the end to log it then to some table.

So, let's say I have function

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;

The problem in the function is:

  1. When I run this manually, it works well, difference is clear. E.g. I use extract to parse the interval: extract(hour from diff)*60*60 + extract(minute from diff)*60 + extract(second from diff)

  2. When I set up the job and the job runs this function I have a big problem: it returns negative result, which as I, after some tests, understand is generated here systimestamp - starttime. Seems like systimestamp in this calculation is taken from Greenwich timezone, and mine is one hour bigger, so this calculation diff interval day to second := systimestamp - starttime; is returning the value like (-1 hour + difference).

By stupid brute-forcing I've found a solution:

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;

which simply writes systimestamp in the variable first, and only then calculates the difference.

My database parameters:

  • Oracle 11.2.0.2.0
  • Timezone +1 Berlin

So now the question: I really want to know is it a bug of my RDBMS or perhaps I do not see some obvious explanation why it is like that? The concrete question is: why during this operation

starttime    timestamp := systimestamp;

it takes one timezone and during this

diff         interval day to second := systimestamp - starttime;

it takes another one in the same procedure of the same session with the same settings?

Was it helpful?

Solution

Is the database timezone DBTIMEZONE the same like your session timezone SESSIONTIMEZONE?

Function SYSTIMESTAMP returns datatye TIMESTAMP WITH TIME ZONE, so you do an implicit convertion into TIMESTAMP datatype.

Datatype of LOCALTIMESTAMP is TIMESTAMP.

Try

starttime    timestamp WITH TIME ZONE := systimestamp;

or

starttime    timestamp := LOCALTIMESTAMP;

You can check with this query in which timezone the Schedule Jobs are running:

SELECT * FROM ALL_SCHEDULER_GLOBAL_ATTRIBUTE where attribute_name = 'DEFAULT_TIMEZONE'

OTHER TIPS

I'm using this approach

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;
/
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top