禁用来自触发器Oracle的触发器

时间:2013-02-23 17:04:14

标签: database oracle plsql triggers

我偶然发现我需要在执行更新之前从触发器中禁用触发器,然后将其重命名。

基本上,我有两张桌子:

  • TIME_SLOTS包含开始时间,结束时间等字段,用于设置时间 程序的槽以及要指定的程序ID(外键) 哪个节目。

  • PROGRAMMES包含所有不同可用程序的列表 &安培;他们的细节。还包含持续时间。

我有一个现有的触发器,当更新或插入TIME_SLOTS时,触发器会从PROGRAMMES中查找持续时间,并确保结束时间=开始时间+持续时间。

我还想添加一个新的触发器,在TIME_SLOTS更改持续时间时更新PROGRAMMES中的结束时间。

我已经设置了这两个触发器,但是当我改变持续时间时:

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行时,我应该在更新之前禁用触发器并在更新后重新设置 - 但由于这是触发器,因此我无法更改触发器...

有什么想法吗?

编辑:我曾经想过我可以设置一个全局变量,并在我不想运行的触发器中检查这个var等等 - 但不确定如何最好地实现?

2 个答案:

答案 0 :(得分:4)

您几乎可以肯定使用EXECUTE IMMEDIATE语句禁用另一个触发器:

EXECUTE IMMEDIATE 'ALTER TRIGGER trigger_name_here DISABLE';

但是,您绝对不应该使用触发器来应用程序逻辑。这是一个混乱的业务,尤其是因为触发器不能保证按顺序触发,而且还因为你遇到的那种“问题”。

所有所描述的功能移动到存储过程或包中会更容易,也更安全,并且只在必要时才使用触发器进行验证。

答案 1 :(得分:0)

当您必须自定义现有功能并且您只能完全控制数据库时,会出现这类问题。因此,您无法通过过程替换插入/更新,您可以做出反应。在这种情况下,您在两个表上都有触发器,并在两个方向上在表之间传播值。