监视长时间运行的PL / SQL块

时间:2011-09-08 15:38:14

标签: sql oracle plsql sqlplus dbms-output

我有一个相当耗时的PL / SQL块,可以从分子结构中构建指纹。我想将输出打印到SQL * Plus控制台,以提供有关已处理的结构数量的反馈。我可以使用dbms_output.put_line

执行此操作

但每次调用新行时都会写入。我想覆盖这条线。

例如,目前我有以下内容。

Structure x of y processed
Structure x of y processed
Structure x of y processed
Structure x of y processed

最后,当我处理数以千计的结构记录时,我填满了缓冲区。

我可以使用哪种方法只覆盖最后一条输出线?

3 个答案:

答案 0 :(得分:15)

使用DBMS_OUTPUT意味着SQL * Plus将在整个PL / SQL块完成之前不显示任何内容,然后显示当前缓冲区中的所有数据。因此,它不是提供持续状态的适当方式。

另一方面,Oracle确实提供了一个包DBMS_APPLICATION_INFO,专门用于帮助您监控正在运行的代码。例如,您可以执行类似

的操作
CREATE PROCEDURE process_structures
AS
  <<other variable declarations>>

  rindex    BINARY_INTEGER;
  slno      BINARY_INTEGER;
  totalwork NUMBER := y; -- Total number of structures
  worksofar NUMBER := 0; -- Number of structures processed
BEGIN
  rindex := dbms_application_info.set_session_longops_nohint;

  FOR i IN (<<select structures to process>>)
  LOOP
    worksofar := worksofar + 1;
    dbms_application_info.set_session_longops(
        rindex      => rindex, 
        slno        => slno,
        op_name     => 'Processing of Molecular Structures', 
        sofar       => worksofar , 
        totalwork   => totalwork, 
        target_desc => 'Some description',
        units       => 'structures');
    <<process your structure with your existing code>>
  END LOOP;
END;

通过单独的SQL * Plus会话,您可以通过查询V$SESSION_LONGOPS视图来监控进度

SELECT opname,
       target_desc,
       sofar,
       totalwork,
       units,
       elapsed_seconds,
       time_remaining
  FROM v$session_longops
 WHERE opname = 'Processing of Molecular Structures';

答案 1 :(得分:1)

您也可以向命名管道发送消息,并让另一个进程从管道中读取消息。

   procedure sendmessage(p_pipename varchar2
                        ,p_message  varchar2) is
      s number(15);
   begin
      begin
         sys.dbms_pipe.pack_message(p_message);
      exception
         when others then
            sys.dbms_pipe.reset_buffer;
      end;

      s := sys.dbms_pipe.send_message(p_pipename, 0);

      if s = 1
      then
         sys.dbms_pipe.purge(p_pipename);
      end if;
   end; 


   function receivemessage(p_pipename varchar2
                          ,p_timeout  integer) return varchar2 is
      n   number(15);
      chr varchar2(200);
   begin
      n := sys.dbms_pipe.receive_message(p_pipename, p_timeout);

      if n = 1
      then
         return null;
      end if;

      sys.dbms_pipe.unpack_message(chr);
      return(chr);
   end;

答案 2 :(得分:0)

我认为你不能。据我所知,dbms_output只是不起作用。

我建议你每隔1000个条目使用put来回显单个点和换行符,看看是否发生了什么事情,然后写入表格或排序当前位置,这样你就可以了解一下。< / p>