2011-09-08 117 views
6

我有一個相當耗時的PL/SQL塊,可以從分子結構中構建指紋。我想將輸出打印到SQL * Plus控制檯,以提供關於已處理多少結構的反饋。我可以這樣做dbms_output.put_line監控長時間運行的PL/SQL塊

然而每次被稱爲新行被寫入。我想覆蓋該行。

例如,目前我有以下。

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

最後我填滿緩衝區,因爲我正在處理數千個結構記錄。

是否有一種方法,我可以使用它只會覆蓋最後一個輸出行?

回答

15

使用DBMS_OUTPUT意味着SQL * Plus將不顯示任何內容,直到整個PL/SQL塊完成,然後顯示當前緩衝區中的所有數據。因此,這不是提供持續狀態的適當方式。

另一方面,Oracle確實提供了一個包DBMS_APPLICATION_INFO,專門用於幫助您監視正在運行的代碼。例如,您可以通過查詢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,很好的模板示例。 – DCookie

0

我不認爲你可以這樣做

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會話,然後你可以的監察進度。據我瞭解dbms_output它只是不這樣工作。

我建議你使用put來回顯每1000條左右的單個點和一個換行符,看看發生了什麼,並寫入表格或序列當前位置,以便您可以看看是否想要知道。

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;