The data model is totally wack. You're only storing a time element, not in the 24 hour clock, and relying on a comparison of PM and AM in each column to avoid getting garbage results. This presumes the process you are tracking does not run for 24 hours or more. Furthermore the generated column is to be in a display format rather than something more useful, such as total elapsed seconds.
But, as an interesting lunchtime challenge, I have decided to have a crack at it anyway. You haven't specified a database so I'm using Oracle.
This function takes two strings, converts them into timestamps, calculates the interval between them and finally returns a string in the desired format:
SQL> create or replace function calc_diff
2 (t1 in load_times.record_time%type
3 , t2 in load_times.upload_time%type)
4 return varchar2
5 deterministic
6 as
7 l_t1 timestamp;
8 l_t2 timestamp;
9 diff INTERVAL DAY (0) TO SECOND (0);
10 return_value varchar2(8);
11 begin
12 l_t1 := to_date('01/01/2000 '||t1, 'dd/mm/yyyy hh:mi:ss am');
13 l_t2 := to_date('01/01/2000 '||t2, 'dd/mm/yyyy hh:mi:ss am');
14 --
15 -- allow for processes which run over midnight
16 --
17 if l_t2 < l_t1
18 then
19 l_t2 := l_t2 + INTERVAL '1' DAY;
20 end if;
21 --
22 -- calculate the interval between the two times
23 --
24 diff := to_dsinterval(l_t2- l_t1);
25 --
26 -- format the return value to exclude the unwanted day and fractional second elements
27 --
28 return_value := lpad( extract (hour from diff), 2, '0')
29 ||':'||lpad( extract (minute from diff), 2, '0')
30 ||':'||lpad(trunc(extract (second from diff)), 2, '0') ;
31 return return_value;
32 end;
33 /
Function created.
SQL>
Now we can use this function is a cool new Oracle 11g feature, virtual columns. This avoids the need for triggers.
SQL> alter table load_times
2 add elapsed_time varchar2(8) GENERATED ALWAYS AS
3 (substr(calc_diff(record_time, upload_time),1,8)) VIRTUAL
4 /
Table altered.
SQL> select * from load_times
2 /
RECORD_TIME UPLOAD_TIME ELAPSED_
----------- ----------- --------
11:37:05 PM 11:39:09 PM 00:02:04
11:44:56 PM 1:7:23 AM 01:22:27
SQL>
Not that in order for this to work, the function CALC_DIFF()
must be marked as DETERMINISTIC
. Also the virtual column has to apply a SUBSTR()
to the function's output, as we cannot constrain it when we declare the function.