Мониторинг долгосрочного блока PL / SQL - PullRequest
6 голосов
/ 08 сентября 2011

У меня довольно длительный блок 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 ]

15 голосов
/ 08 сентября 2011

Использование 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 голос
/ 12 сентября 2011

Вы также можете отправлять сообщения в именованный канал и попросить другой процесс прочитать сообщение из канала.

   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;
0 голосов
/ 08 сентября 2011

Не думаю, что ты можешь. Насколько я понял, dbms_output просто так не работает.

Я рекомендую вам использовать put для отображения одной точки и новой строки каждые 1000 или около того записей, чтобы увидеть, что что-то происходит, и записать в таблицу или последовательность текущую позицию, чтобы вы могли посмотреть, если хотите знать.

...