2010-09-17 128 views
6

當觸發器無法正常工作時,我不知道錯誤信息的位置。Oracle調試技術

我的編寫觸發器的工具是Oracle的Sql Developer工具,我對如何調試它的知識幾乎不存在。能夠找到有關「幕後」事件的有用信息的指點是什麼?另外,Sql Developer是否有更好的工具用於連接,測試,調試等?

到目前爲止,我的方法一直是編寫一些東西(例如觸發器),用單個插入/刪除來測試它,然後希望它能從它們開始工作。有沒有更好的方法來確保它正在做你想要的東西?例如,使用select語句,無論如何要查看(在調試狀態或某事中)select的每個級別以及它如何減少結果?任何提示不勝感激。

回答

12

首先,所有代碼都能正常工作。它只是沒有做你期望的事情。其次,「不要從這裏開始」,或者特別不要使用觸發器。如果觸發器要觸發每一行,它基本上會強制切換到行級處理。實際上最好是將邏輯放到您調用的存儲過程中。然後,您就會有一個開始(您驗證輸入的地方)以及一個結束和一條邏輯路徑。在遵循一條路徑時,它們更容易調試。

三,永遠不要測試你不知道如何處理的錯誤。如果你沒有抓住它,它會向客戶發出一個錯誤報告,說明出了什麼問題(錯誤信息)和哪裏(即錯誤/調用堆棧)。如果你試圖去捕捉它,你必須知道如何處理它(如果你不知道這個趨勢是忽略它 - 這是壞的)。

最後,您不能輕易看到選擇的每個「圖層」。解釋計劃通常會告訴你它是如何進行的。 v $ session_longops可以指出它當前正在做什麼。當前的等待事件可以提供關於它當前正在處理的表/塊/行的線索。

+0

提及解釋計劃+1,+1代表「所有代碼正常工作」:) – 2010-09-17 02:54:11

+0

我沒有給出足夠的信息在我原來的。我寫了一個觸發器,可以處理單個插入但不是多個,我認爲是因爲死鎖問題。我認爲我解決了這個問題,但是當它發生時,它是一個「無聲錯誤」。是否有日誌或我可以找到類似的信息?另一個後續步驟:存儲過程最終會不同於觸發器?假設我有一個表,一個外部源將數據放入,另一個表我想根據第一個表放入數據,並使用當前數據更新它。存儲過程如何>觸發? – 2010-09-17 05:02:14

+0

There沒有沉默的錯誤,或者它的錯誤,失敗和回滾,或者它成功了,但很有可能,你已經告訴它它沒有做你想做的事情,因爲行級觸發器在SQL語句存在讀取一致性問題,這往往會導致出現複雜且容易出錯的變通方法。 – 2010-09-17 22:03:50

10

如果您必須調試觸發器,那麼粗略簡單的方法是使用DBMS_OUTPUT

例如

SQL> CREATE OR REPLACE TRIGGER mytrigger 
    BEFORE UPDATE ON mytable 
    FOR EACH ROW 
    ... 
    BEGIN 
     DBMS_OUTPUT.put_line('mytrigger STARTING'); 
     ... do some logic ... 
     DBMS_OUTPUT.put_line('old=' || :OLD.mycolumn); 
     DBMS_OUTPUT.put_line('new=' || :NEW.mycolumn); 
     DBMS_OUTPUT.put_line('mytrigger FINISHED'); 
    END; 
    /

SQL> SET SERVEROUT ON 
SQL> UPDATE mytable SET mycolumn = mycolumn + 1; 
2 rows updated. 

mytrigger STARTING 
old=10 
new=11 
mytrigger FINISHED 
mytrigger STARTING 
old=20 
new=21 
mytrigger FINISHED 
+0

好的信息,謝謝。 – 2010-09-17 04:58:11

1

應用 我在www.quest.com/toad/toad-for-oracle.aspx使用一個程序從任務稱爲TOAD可用。

如上所述,DBMS_OUTPUT非常方便。在你的編輯器中,確保你啓用了輸出窗口。

PL/SQL適用於代碼的「塊」,您可以使用EXCEPTION關鍵字捕獲它。

(請原諒我的格式,不知道如何爲網絡格式)

DECLARE 
    C_DATE_FORMAT VARCHAR2(20) := 'DD-Mon-YYYY'; 
    C_TIME_FORMAT VARCHAR2(20) := 'HH24:MI:SS'; 
    C_NOT_IMPLEMENTED_CODE CONSTANT NUMBER(5) := -20200; 
    C_NOT_IMPLEMENTED_MESSAGE CONSTANT VARCHAR2(255) := 'Not implemented'; 
    not_implemented EXCEPTION; -- user defined exception 
BEGIN 
    --RAISE not_implemented; -- raise user defined exception 
    RAISE_APPLICATION_ERROR(C_NOT_IMPLEMENTED_CODE, C_NOT_IMPLEMENTED_MESSAGE); -- user defined exception 
EXCEPTION -- exception block 
    WHEN not_implemented THEN -- catch not_implemented exception 
     DBMS_OUTPUT.PUT_LINE('Error: Not implemented'); 
    WHEN OTHERS THEN -- catch all other exceptions 
     DBMS_OUTPUT.PUT_LINE('Error occured.'); 
     DBMS_OUTPUT.PUT_LINE('Date: ' || TO_CHAR(SYSDATE, C_DATE_FORMAT)); 
     DBMS_OUTPUT.PUT_LINE('Time: ' || TO_CHAR(SYSDATE, C_TIME_FORMAT)); 
     DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE); 
     DBMS_OUTPUT.PUT_LINE('Error message: ' || SQLERRM); --deal with error 
     RAISE; -- raise to calling object 
END; 
0

也有在dbForge的好Oracle debugger工具Studio for Oracle具有逐步執行的代碼,斷點,調用堆棧,監視器,用於Oracle存儲函數和過程調試自動化的變量評估機制。