7

我有一个相当耗时的 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

最终,当我处理数千条结构记录时,我填满了缓冲区。

有没有我可以使用的方法来覆盖最后的输出行?

4

3 回答 3

16

UsingDBMS_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';
于 2011-09-08T15:50:11.533 回答
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;
于 2011-09-12T10:44:54.537 回答
0

我不认为你可以。据我了解 dbms_output 它只是不能那样工作。

我建议您使用 put 每隔 1000 个左右的条目回显一个点和一个换行符,以查看正在发生的事情并将当前位置写入表格或排序,以便您可以查看如果您想知道。

于 2011-09-08T15:51:41.097 回答