2017-04-20 108 views
-1

我試圖做一個觸發器,但我得到了一個突變表錯誤。 SQL代碼是這樣的:Oracle SQL觸發器上的突變表

CREATE OR REPLACE TRIGGER CHK_Apartado_D 
BEFORE INSERT OR UPDATE ON CONTRACTS 
FOR EACH ROW 
DECLARE 
errorvisualizacion EXCEPTION; 
local_enddate DATE; 
BEGIN 
    SELECT enddate INTO local_enddate FROM CONTRACTS WHERE clientid=:new.clientid; 
    IF local_enddate > SYSDATE OR local_enddate IS NULL 
    THEN 
    UPDATE CONTRACTS SET enddate = SYSDATE - 1 WHERE clientid=:new.clientid; 
    END IF; 
END CHK_Apartado_B; 
/

而我得到的錯誤是這樣的:

Informe de error - 
Error SQL: ORA-04091: table HR.CONTRACTS is mutating, trigger/function may not see it 
ORA-06512: at "HR.CHK_APARTADO_D", line 5 
ORA-04088: error during execution of trigger 'HR.CHK_APARTADO_D' 
ORA-06512: at "HR.CHK_APARTADO_D", line 8 
ORA-04088: error during execution of trigger 'HR.CHK_APARTADO_D' 
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it" 
*Cause: 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. 
*Action: Rewrite the trigger (or function) so it does not read that table. 

當我插入一個新的合同我要檢查,如果該客戶端在實際的其他合同日期,如果他有我必須更新結束日期contracte到昨天,讓新的INSERT。那麼,我該如何防止變異表呢?

+0

這似乎是一個最近令人困惑的練習: [here](http://stackoverflow.com/q/43494370/266304),[here](http://stackoverflow.com/q/43483253/266304),[here](http://stackoverflow.com/ q /二十六萬六千三百○四分之四千三百二十三萬八千四百八十八);哦,去年的這個時候,[這裏](http://stackoverflow.com/q/36372988/266304),... –

+0

@AlexPoole - 似乎我們需要一個規範的答案,只是繼續關閉重複。 – APC

+0

@APC - 是一個規範的答案,將有效地作爲適當的分配答案,但?儘管我不確定我是否看到過任何地方的作業,暗示了分配者實際上在尋找什麼答案......或者至少不是答案,我會很樂意嘗試寫出* 8-) –

回答

1

觸發器觸發更新或插入CONTRACTS,然後嘗試更新CONTRACTS,觸發觸發器....查看問題?

您需要計算出enddate,然後實際進行插入/更新。

1

一個常見的解決方案是Using Compound Triggers to Avoid Mutating-Table Error

更好的是,不要嘗試使用觸發器來實現複雜的業務邏輯。相反,使用實現業務規則的程序insert_contract構建API包,並確保(通過特權)用戶調用該API,而不是直接插入表中。觸發器很快就會變得非常混亂。