查询的开始和结束时间

时间:2018-08-07 07:36:58

标签: sql oracle plsql oracle12c

作为存储过程要求的一部分,我需要提供特定子查询的开始和结束时间。例如,假设我的查询是:

SELECT  price
  FROM  vehicles
  WHERE wheels < 3

我的存储过程的输出应该是指向如下表的引用器:

price  start_time          end_time
12000  2018-08-08 08:42:31 2018-08-08 08:42:52
130000 2018-08-08 08:42:31 2018-08-08 08:42:52
6000   2018-08-08 08:42:31 2018-08-08 08:42:52
3500   2018-08-08 08:42:31 2018-08-08 08:42:52

其中start_time是我启动选择语句的时间,而end_time是它完成的时间。

我尝试了以下操作:

WITH start_time AS
( SELECT sysdate AS start_time
    FROM dual
), main_query AS
( SELECT  price
    FROM  vehicles
    WHERE wheels < 3
), end_time AS
( SELECT sysdate AS end_time
    FROM dual
)
SELECT       main_query.*
     ,       TO_CHAR(start_time, 'YYYY-MM-DD HH24:MI:SS') AS start_time
     ,       TO_CHAR(end_time, 'YYYY-MM-DD HH24:MI:SS') AS end_time
  FROM       main_query
  CROSS JOIN start_time
  CROSS JOIN end_time
;

但是开始时间和结束时间都说相同的时间。

我知道这是一个非常规(且笨拙)的要求,但是需要必须...

2 个答案:

答案 0 :(得分:4)

如果是过程的一部分,则让它分为两部分进行处理。首先,我们获取数据,然后将其返回。

我们创建一个对象来临时存储数据:

create type r_price_index as object (
    price  number(10,2));
create type t_price_index is table of r_price_index;

然后在您的proc中:

declare
v_price_index t_price_index;
v_t_stamp1    date;
v_t_stamp2    date;
v_cur         sys_refcursor;
v_out         sys_refcursor;

begin

v_t_stamp := sysdate; -- The start time

open v_cur for
  SELECT  price
  FROM  vehicles
  WHERE wheels < 3;
fetch v_cure bulk collect into v_price_index; -- Store the data in the object
close v_cur;
v_t_stamp2 := sysdate; -- The end time

open v_out for -- Output the stored data
  select price, v_t_stamp1 as s_time, v_t_stampt2 as e_time
  from table(v_price_index);
end;

您需要进行一些异常处理(no_data_found等),但这应该可以为您提供所需的确切信息。

答案 1 :(得分:2)

systimestamp中使用函数sysdateSQL的结果时会对其进行缓存,因此它们总是返回查询开始的时刻。

创建自定义函数my_timestamp而不进行缓存,因此每次获取每一行都会调用一次。并且考虑到sysdate具有第二精度,因此有机会错过快速查询的时间间隔。这就是systimestamp对于基准测试更有用的原因。

取决于如何使用它,有时应用/*+ materialize */提示以确保查询仅执行一次是很重要的,否则在较小的结果集上,优化器可能会决定多次运行子查询以产生时间结果不一致的。

with
  function my_timestamp return timestamp is begin return systimestamp; end;

  main_query AS (      
    SELECT /*+ materialize */
      my_timestamp AS custom_ts, 
      systimestamp AS standard_ts,
      T.* 
    FROM vehicles T  
  )  
select (select max(custom_ts) from main_query) as end_time,
       (select min(custom_ts) from main_query) as begin_time,
       T.*
from main_query T;

PS。另外,使用a look at dbms_utility.get_time函数来测量代码执行时间。