从触发器 Oracle 禁用触发器

Dav*_*rke 3 database oracle triggers plsql

我偶然发现了一种情况,我需要在执行更新之前从触发器中禁用触发器,然后再重新启用它。

基本上,我有两个表:

  • 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'
Run Code Online (Sandbox Code Playgroud)

这显然是因为当我更改持续时间时,第二个触发器会更新TIME_SLOTS. 触发器TIME_SLOTS触发并查找持续时间 - 持续时间正在发生变化,我得到了如上的错误。

在我看来,当我TIME_SLOTS使用新计算的结束时间更新行时,我应该在更新之前禁用触发器并在更新后重新启用 - 但由于这是触发器,我无法更改触发器......

有任何想法吗?

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

Ben*_*Ben 5

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

EXECUTE IMMEDIATE 'ALTER TRIGGER trigger_name_here DISABLE';
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我们都建议的是,与其直接针对第一个表发出 INSERT 或 UPDATE 语句,然后依靠触发器来更新第二个表,不如根据需要简单地调用存储过程来 INSERT/UPDATE 两个表,而不是使用为此目的触发。 (4认同)