2009-11-13 48 views
19

我有一些可能需要幾分鐘才能運行的pl/sql程序。在開發它們時,我添加了一些打印語句來幫助調試,並提供一些反饋和進度指示器。最初,我在小型測試臺上運行這些測試,輸出幾乎是瞬間的。現在我正在測試運行幾分鐘的大型測試集,我發現打印到控制檯不再合適,因爲在程序結束之前沒有任何東西被打印。我習慣於在不緩衝輸出並立即打印的環境中工作,並且添加簡單的打印語句以進行簡單的調試和診斷是很常見的。Oracle PL/SQL - 即時輸出/控制檯打印提示

是否有可能在pl/sql中立即打印輸出(未緩衝)?如果不是,人們推薦什麼替代方案來獲得類似的結果?

回答

17

你可以擁有,使用一個自治事務類似消息寫入表的程序:

procedure log (p_message) 
is 
    pragma autonomous_transaction; 
begin 
    insert into message_log (user, datetime, message) 
    values (user, sysdate, p_message); 
    commit; 
end; 

然後從另一個Oracle會話監控表。

+1

關於pragma autonomous_transaction的更多信息http://stackoverflow.com/questions/1335331/autonomoustransaction – caddis 2009-11-13 17:57:32

+1

這看起來不錯,我今天可能會試試:) 它與使用管道的其他建議相比如何?哪個更容易查看和監控? – FrustratedWithFormsDesigner 2009-11-16 16:42:08

+0

我還沒有使用管道方法,所以不能對此發表評論。表格方法的一個不同是消息是持久的。這可能是一個優點,但它也意味着你必須管理它們,以便表格不會無限增長! – 2009-11-16 16:51:05

8

我們對此有個小竅門。

你可以使用DBMS_APPLICATION_INFO.set_client_info(「某些信息在這裏」); 創建一些變量並替換「」中的字符串。

並使用從v $ session中選擇client_info來監視進度。

+0

我有權訪問v $ session_longops和v $ session_connect_info,它們都沒有client_info字段。 v $ session_longops會一樣好嗎? – FrustratedWithFormsDesigner 2009-11-13 16:02:39

+1

不,您需要使用v $會話視圖。如果您無法訪問,請問DBA。 – 2009-11-13 16:37:12

1

通常有兩種選擇:

  • 將輸出發送到Oracle表 (或臨時表)
  • 寫的(數據庫主機)文件系統與UTL_FILE

如果您沒有操作系統訪問數據庫主機的權限,您仍然可以寫入dbhost文件系統並將Oracle外部定義的表綁定到該文件,以便可以使用SELECT查詢該文件。

1

它可能取決於您的客戶端工具。我暫時還沒有使用SQL * Plus,但是當我在PL/SQL Developer中調試過程時,我打開一個命令窗口併發出一個SET SERVEROUTPUT ON命令。然後當我執行程序時,任何由DBMS_OUTPUT.PUT_LINE打印的東西都會立即顯示出來。

編輯:你是對的,我想我只是看到與大量的輸出或東西。無論如何,我做了一些在線搜索,碰到這個log4plsql - 可能會有用。

+0

我是PL/SQL Developer的用戶,不起作用。腳本執行完畢後,所有輸出都會立即打印出來。 – FrustratedWithFormsDesigner 2009-11-13 15:55:30

1

另一種方法是使用返回日誌信息的流水線函數。請參閱此處的示例:http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html當您使用流水線功能時,不必使用其他SQLPLUS/Toad/sql開發人員等...會話。

+0

這很有趣,但是我不必將現有的函數修改爲流水線,或者可能將它包裝在流水線函數中? – FrustratedWithFormsDesigner 2009-11-16 16:25:45

+0

當然,你必須改變你的代碼。只是將它封裝在流水線函數中並不能幫助您,因爲您希望立即進行日誌記錄,而不僅僅是在完成某些事情時進行日誌記錄。 – tuinstoel 2009-11-16 18:42:35

2

我一直在使用dbms_pipe來達到這個目的。將消息發送到命名管道,並從另一個會話讀取它們。當寫入和讀取過程可能連接到不同的節點時,此方法可能無法在RAC環境中使用。

或者,您可以使用使用「pragma autonomous_transaction」在自己的會話中運行的過程將消息插入到表中。您可以從另一個會話查詢這些消息

編輯:我看到我的第二個選項已被提及。

+0

這兩個看起來都像是有趣的可能性,儘管當我嘗試使用dbms_pipe包時,出現錯誤(可能與權限相關)。 每種方法的優缺點是什麼?我對Oracle管道瞭解不多,所以我不知道如何評估,但它比表驅動解決方案更接近我想要的。 – FrustratedWithFormsDesigner 2009-11-16 16:48:10

1

您可以在PL/SQL Developer中使用DBMS管道和管道查看器異步捕獲放入管道中的所有信息。

小心只有在有人閱讀時纔將東西放入管道中。否則,當管道已滿時,您的呼叫將失敗。

還有使用事件的可能性,PL/SQL Developer還有一個事件監視器。文檔應該提供一個如何去做的例子。

+0

這看起來不錯,但我得到一個錯誤:「標識符」DBMS_PIPE'必須聲明「,我想我需要與DBA談談此事。可能是權限問題。 – FrustratedWithFormsDesigner 2009-11-16 16:37:42

0

另一個選擇是讓你的PL/SQL調用一個過程來發送一封包含日誌消息的電子郵件。這要求您的數據庫具有電子郵件發送功能,可以使用UTL_SMTP添加電子郵件發送功能。