2013-02-23 37 views
2

我已經偶然發現了一種情況,即需要在執行更新之前從觸發器中禁用觸發器,然後重新對其進行更新。從觸發器中禁用觸發器Oracle

基本上,我有兩個表:

  • TIME_SLOTS具有諸如開始時間,結束時間,要設置一個節目的時間 時隙以及程序ID(外鍵)來指定 哪個節目。

  • PROGRAMMES包含所有不同可用程序的列表 &其詳細信息。還包含一個持續時間。

我有一個現有的觸發器,更新或插入到TIME_SLOTS時,觸發從PROGRAMMES查找的持續時間,並確保結束時間=開始時間+時間。

我還想在PROGRAMMES中更改持續時間時添加一個新的觸發器,以更新TIME_SLOTS中的結束時間。

我已經設置這兩個觸發器,但改變了時間,當我得到:

One error saving changes to table "SE217"."PROGRAMMES": 
Row 1: ORA-04091: table SE217.PROGRAMMES is mutating, trigger/function may not see it 
ORA-06512: at "SE217.SCHEDULES_VALID_TIMES", line 19 
ORA-04088: error during execution of trigger 'SE217.SCHEDULES_VALID_TIMES' 
ORA-06512: at "SE217.UPDATE_END_TIME", line 5 
ORA-04088: error during execution of trigger 'SE217.UPDATE_END_TIME' 

這顯然是因爲當我改變的時間,第二個觸發器去更新TIME_SLOTS結束時間。 TIME_SLOTS上的觸發器會觸發並查找持續時間 - 持續時間會發生變化,並會出現上述錯誤。

在我看來,當我用新計算的結束時間更新TIME_SLOTS行時,我應該在更新之前禁用觸發器並在更新之後進行更新 - 但由於這是觸發器,我無法更改觸發器......

任何想法?

編輯:我有一個想法,我可以設置一個全局變量,並檢查此觸發器,我不想運行等變量 - 但不知道如何最好地實現?

+0

恕我直言,使用包變量是一個不錯的選擇。 – 2013-02-23 17:15:02

+0

@EgorSkriptunoff你可以在包中存儲觸發器嗎?這將如何工作? – swiss196 2013-02-23 17:26:58

+0

變量應該存儲在一個包中。 – 2013-02-23 17:32:43

回答

3

您可以從另一個使用EXECUTE IMMEDIATE語句幾乎肯定禁用一個觸發器:

EXECUTE IMMEDIATE 'ALTER TRIGGER trigger_name_here DISABLE'; 

但是,你絕對不應該使用應用程序邏輯觸發器中。這是一個混亂的業務,至少由於事件觸發器不能保證順序開火,但也是因爲你遇到的那種「問題」。

將您所描述的功能移動到存儲過程或程序包並將觸發器僅用於驗證目的所需的情況下,將更容易且更安全地將全部移動到存儲過程或程序包。

+0

我有點理解你的意思,但並不真正知道如何實現這一點。當第一個變化時,我需要一個觸發器來更新另一個表格嗎?你是否建議在觸發器中調用該過程? – swiss196 2013-02-25 01:36:40

+3

我們都在暗示的是,不是直接對第一個表發出INSERT或UPDATE語句,而是依靠觸發器來更新第二個表,您應該簡單地調用存儲過程來根據需要調用INSERT/UPDATE兩個表,而不是爲此目的使用觸發器。 – Ben 2013-02-25 08:59:51

0

當您必須自定義現有功能並且您完全控制數據庫時,會出現這些類型的問題。所以你不能通過程序替換插入/更新,你可以做出反應。在這種情況下,您在兩個表上都有觸發器,並在兩個表中的表之間傳播值。