2015-03-31 141 views
0

所以我有這個表:創建觸發器刪除行

CREATE TABLE orders_rows (
    order_id  NUMBER(10) PRIMARY KEY, 
    row_num  DATE NOT NULL, 
    p_id   NUMBER(10) NOT NULL, 
    quantity  NUMBER(10) NOT NULL, 
); 

我想創建一個觸發器,當更新改變量爲0(零) - >刪除此列。

我嘗試這樣做:

CHECK_ORDER_ROW trigger:

create or replace 
TRIGGER check_order_row 
    AFTER INSERT OR UPDATE on orders_rows 
    for each row 
BEGIN 
    if :new.quantity = 0 then 
    DELETE_ORDER_ROW(:new.order_id, :new.row_num); 
    end if; 
END; 

DELETE_ORDER_ROW是具體的步驟:

DELETE_ORDER_ROW procedure:

create or replace 
PROCEDURE delete_order_row (p_order_id NUMBER, p_row_num NUMBER) 
IS 
BEGIN 
    DELETE orders_rows WHERE (order_id = p_order_id and row_num = p_row_num); 
    COMMIT; 
END; 

但是,當我嘗試更新:

update orders_rows set quantity=0 where (order_id=1 and row_num=1); 

我收到的錯誤:

A trigger (or a user defined plsql function that is referenced in 
      this statement) attempted to look at (or modify) a table that was 
      in the middle of being modified by the statement which fired it. 

我能做的任何更改嗎?或嘗試其他選項來做到這一點?

在此先感謝!

+0

這是你正在談論的遞歸觸發器。不要以爲Oracle支持一個。 – Rahul 2015-03-31 18:28:20

回答

2

你可能不能(或至少你不應該)。

表中的行級觸發器通常不會查詢同一個表而不會導致突變表異常。如果確實確定,可以創建一個包,在該包中創建一個值爲order_id的值集合,創建一個用於初始化集合的before語句觸發器,創建一個行級觸發器,用:new.order_id填充該集合,然後創建一個after語句觸發器,通過集合迭代並稱爲delete_order_row。然而,這是很多動人的事情來處理。對於將quantity設置爲0的應用程序代碼來刪除行通常會更有意義。將邏輯放入刪除應用程序剛剛插入(或更新)的行的觸發器中通常會導致應用程序流很難遵循(部分原因是您無法立即看到整個流,因此您一直在尋找哪些副作用觸發器正在創建)以及很難理解和調試的錯誤。

如果您決定使用觸發器並且您不想使用三觸發解決方案,也可以重命名該表,創建一個名爲order_row的視圖並在視圖上創建一個instead of觸發器update根據quantity值查看基表上的updatedelete。然而,這爲您的代碼增加了一個額外的間接層,它仍然會使應用程序流很難遵循。

+0

我想知道,如果數量達到0時刪除一行不會與同一行的併發更新衝突?對我來說,感覺就像是一場競賽。 – 2015-03-31 18:39:05

+0

我沒有看到競賽狀況。執行更新的會話必須在更新發生之前鎖定行。同一會話應該能夠刪除行而不需要獲取任何額外的鎖,並且在觸發器必須在'update'所在的同一個事務上下文中觸發時,其他會話不能修改臨時行中的行。您可以通過執行諸如從定義爲自治事務的觸發器發出刪除來創建線程問題。但這是一個非常糟糕的主意。 – 2015-03-31 18:53:40

+0

謝謝你的回覆。但是,如果OP有兩個同時查詢,一個可能將數量減少到0,另一個增加數量 - 取決於它們處理的順序,如果首先處理_增量_(數量爲「N」 - >'N + M' - >'M')。 _或_,如果增加的更新在減少之後被處理,則它將在該行被刪除時失敗(數量'N' - >'0' - 刪除該行,因此在那之後不能更新它)。這個推理是否有效,或者我在這裏錯過了什麼? – 2015-03-31 19:12:19