2012-10-02 83 views
0

我有一個表,我試圖做一個插入/更新取決於我給的值。但插入不適用於這個特定的表,但它適用於腳本運行的以前的表。PLSQL觸發器可能導致INSERT INTO以靜默方式失敗?

爲了測試這個問題,我在Oracle的sqldeveloper中放入了一些匿名塊,這些塊根據是否存在鍵來插入或更新。更新似乎工作正常,但是當涉及到插入一個新行時,沒有插入任何內容。

如果我有這個表:

COFFEE_ID  TEA_ID  NAME  
    11    100  combo 1 
    12    101  combo 2 
    13    102  combo 3 

這樣做將不插入任何東西,反而會移動到下一個匿名塊:

begin 
     insert into COFFEE_TEA(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4'); 
    exception when dup_val_on_index then 
     update .... 
    end; 

    .... 

我懷疑它做的在這張桌子上觸發。它是一個BEFORE EACH ROW觸發器類型,它會向其他表中插入數據。在觸發器中沒有異常處理,所以我猜測它必須失敗,但不報告它(在運行腳本時不會在sqldeveloper中顯示)。

我的兩個問題是,

當觸發運行時,會發生什麼,如果它試圖將ID插入到另一表已存在?看起來它默默地失敗?

我該如何解決這個問題?我不確定自己是否可以更改觸發器代碼,但是可以在我的匿名塊中捕獲錯誤(假設它實際上是導致問題的觸發器)。如果是這樣的話,我如何知道如果它默默地失敗,會發生什麼異常?


我刪除了sqldeveloper中的異常,它告訴我唯一的約束被違反了。即通過觸發器將數據插入到另一個表中是原因。

回答

0

觸發器不會修改表上的DML進程。除去異常塊,如果COFFEE_TEA是表,則插入將成功或失敗,並出現錯誤。

換句話說,下面的腳本將永遠輸出0,如果COFFEE_TEA是一個表:

BEGIN 
    INSERT INTO coffee_tea(COFFEE_ID, TEA_ID, NAME) values (14, 103, 'combo 4'); 
    dbms_output.put_line(sql%rowcount); 
END; 
+0

謝謝,我刪除了sqldeveloper中的異常,它告訴我一個唯一的約束被違反了,即通過觸發器插入到另一個表中的數據是原因。我想我現在可以捕捉到這個異常並執行相應的操作。有沒有更好的辦法? – user1636922

+0

@ user1636922可能合併聲明可能是對你更好的方法。 – Maddy

3

你更多的信息告訴我們,您的觸發投擲ORA-00001,獨特的鍵衝突。這是DUP_VAL_ON_INDEX異常處理的錯誤。所以看起來你的異常處理程序應該是處理COFFEE_TEA上的關鍵違規問題,它也吞噬了觸發器中的異常。亂。

有兩種可能的解決方案。一種是在觸發代碼中提供體面的錯誤處理。另一種是使用MERGE進行數據加載例程。

我總是比較喜歡MERGE作爲執行upserts的機制,因爲我不喜歡使用異常來處理合法的期望狀態。 Find out more

理想情況下,你應該兩個都做。觸發器應該是自包含的代碼:在與表格交互的例程上強加未處理的異常會破壞封裝。