处理在运行时执行的多个查询的列表。

时间:2017-02-03 12:44:33

标签: plsql

我有一个存储在Oracle DB表中的查询列表。我的要求是逐个获取每个查询并在过程中触发它们并在另一个表中记录它们的开始结束和已用时间

我的问题是我应该如何处理列列表,因为每个查询都会有所不同,并且在运行时无法预测列数及其数据类型。

请建议出路。

目前,我已经写下了以下代码。这里我附上了使用count()获取的每个查询以避免问题。但是,计数()查询所用的实际时间将与执行原始查询所用的时间不同。

非常感谢!

DECLARE
  before_time        TIMESTAMP;
  after_time         TIMESTAMP;
  elapsed_time_in_ms NUMBER;
  stmnt CLOB; --varchar(32000);
  counts   NUMBER;
  sql_no   NUMBER;
  err_mess VARCHAR2(100);
  CURSOR get_queries
  IS
    SELECT * FROM SLOW_RUNNING_SQL WHERE curr_ind = 1;

FUNCTION get_elapsed_time(
    start_time_in TIMESTAMP ,
    end_time_in   TIMESTAMP )
  RETURN NUMBER
AS
  l_days         NUMBER;
  hours        NUMBER;
  minutes      NUMBER;
  seconds      NUMBER;
  milliseconds NUMBER;
BEGIN
<calculates elapsed time in milliseconds and returns that>
  RETURN milliseconds  ;
END;
BEGIN
  dbms_output.put_line(CURRENT_TIMESTAMP);
  before_time := SYSTIMESTAMP;
  FOR i IN get_queries
  LOOP
    stmnt  := i.SQL_DESC;
    sql_no := i.sql_no;
    stmnt  := 'SELECT count(*) FROM ('||stmnt||') a';
    dbms_output.put_line(stmnt);
    EXECUTE IMMEDIATE stmnt INTO counts;
    after_time        := SYSTIMESTAMP;
    elapsed_time_in_ms:= get_elapsed_time(before_time,after_time);
    dbms_output.put_line(elapsed_time_in_ms);
    INSERT
    INTO query_performance_log VALUES
      (
        i.sql_no,
        stmnt,
        counts,
        before_time,
        after_time,
        elapsed_time_in_ms/1000,
        'No exception',
        elapsed_time_in_ms );
    dbms_output.put_line(stmnt);
    dbms_output.put_line(counts);
    dbms_output.put_line(after_time);
    dbms_output.put_line(TO_CHAR(after_time - before_time));
    COMMIT;
  END LOOP;
  ROLLBACK;
EXCEPTION
WHEN OTHERS THEN
  err_mess:= SQLERRM;
  INSERT
  INTO query_performance_log VALUES
    (
      sql_no,
      stmnt,
      0,
      NULL,
      NULL,
      0,
      err_mess,
      0
    );
  dbms_output.put_line(SQLERRM);
  ROLLBACK;
END;

1 个答案:

答案 0 :(得分:0)

可能适合您的解决方案是为查询返回的每一行选择一个常量,并生成bulk collect INTOvarchar2个变量的集合。

以下是您要找的内容:

-- declare a list of varchar2:
CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);

-- then use this type in your proc.:
[..]
declare
  v_res   t_my_list;
[..]

-- then run the query
execute immediate 'SELECT ''x'' FROM ('||stmnt||') ' 
  bulk collect into v_res;

如果您的查询选择的列“简单”,则上述内容应该足够公平以评估效果。但是如果你开始调用你在select中检索的数据的其他函数和过程,那么它就更复杂了。

在另一种情况下,那么你应该尝试一些工作来构建返回列的串联(并在VARCHAR2(100)的声明中放大t_my_list)。这意味着您开始使用stmnt并提取列,其中一部分是,左右替换''||''