2011-06-29 60 views
2

我正在使用Oracle 10g數據庫,並且在事務內部觸發器出現問題。 Table A有3個觸發器:插入前一個,更新前一個,最後一個刪除。無論何時觸發觸發器,它都會在table B上寫上一行,就像某種日誌。 所有觸發器均在"before xxx""on each row"上配置。使用單個查詢,我可以看到他們正在工作。Oracle:事務內的觸發器(2條語句)

但是,當我一個交易,(通常情況下,我修改的線條,然後我刪除了,所以一個updatedelete)在做兩個查詢修改同一行,只有第一個觸發器(update)運行。在交易結束時,我可以看到我的table A行已被刪除,但table B中只有一行顯示更新操作,但不是刪除操作。

我可能配置有誤。它是否來自觸發器配置?

回答

6

第二個觸發器沒有理由不會觸發,還有其他事情正在發生。

這裏有一個小的測試案例,顯示了所有正確觸發火警當單個事務修改單排幾次:

SQL> CREATE TABLE a (ID NUMBER); 

Table created 

SQL> CREATE TABLE b (action VARCHAR2(3), id_old NUMBER, id_new NUMBER); 

Table created 

SQL> CREATE TRIGGER trg_a_ins BEFORE INSERT ON a FOR EACH ROW 
    2 BEGIN 
    3  INSERT INTO b VALUES ('ins', :old.id, :new.id); 
    4 END; 
    5/

Trigger created 

SQL> CREATE TRIGGER trg_a_upd BEFORE UPDATE ON a FOR EACH ROW 
    2 BEGIN 
    3  INSERT INTO b VALUES ('upd', :old.id, :new.id); 
    4 END; 
    5/

Trigger created 

SQL> CREATE TRIGGER trg_a_del BEFORE DELETE ON a FOR EACH ROW 
    2 BEGIN 
    3  INSERT INTO b VALUES ('del', :old.id, :new.id); 
    4 END; 
    5/

Trigger created 

SQL> INSERT INTO a VALUES (1); 

1 row inserted 

SQL> UPDATE a SET ID = 2 WHERE ID = 1; 

1 row updated 

SQL> DELETE FROM a WHERE ID = 2; 

1 row deleted 

SQL> select * from b; 

ACTION  ID_OLD  ID_NEW 
------ ---------- ---------- 
ins      1 
upd    1   2 
del    2 
+0

感謝您的測試用例。結構的圖片接近我們的(當然更復雜)。我試過了,它工作。確實,還有其他的東西。 – Ashygan

0

由於@Vincent的Malgrat說,別的東西是怎麼回事。表B有一個日期列,其上有唯一的索引?想到的第一種可能性是這兩個記錄是以相同的日期(審計)值插入到最近的一秒;索引衝突導致刪除中的第二次插入錯誤;但是在刪除觸發器內被壓扁。我知道這很具推測性,而且在時間戳列上的可能性會小一些,如果時間恰到好處,偶爾會按預期工作。

+0

表B沒有日期列(雖然它計劃在不久的將來,它不會被索引)。相反,我在表B上有一個主鍵,它的值是使用表B上的觸發器(在插入之前,對於每行)從序列中獲取的。它可能來自第二個觸發器? 另一個信息:我使用Hibernate來訪問數據庫(插入,更新,刪除)。我知道當Oracle觸發來自觸發器的錯誤時,我的Java代碼中有一個異常。儘管如此,在這種情況下,我沒有看到Oracle出現異常。 – Ashygan

+0

其中一個觸發器可能會壓縮一個異常,所以Hibernate將沒有機會看到它,但這只是一個猜測。將表結構和觸發代碼添加到問題可能會有所幫助。 –

0

ORM有可能(也是最理想的)'壓縮'對單個記錄的多個改變。因此,代碼可能更新三個屬性,並且ORM可能已經在其緩存中多次更新記錄/實例,但只在事務結束時發送單個UPDATE語句。或者,如果記錄最終被刪除,它可能會跳過任何更新並刪除原始記錄。

這就是說,我不能解釋爲什麼在沒有觸發DELETE觸發器的情況下可以刪除一條記錄。我假設你正在使用真正的刪除而不是「軟」刪除(它將一條記錄標記爲已刪除,並將其從視圖中隱藏起來)。