【发布时间】:2013-02-09 04:33:16
【问题描述】:
我偶然发现了一种情况,我需要在进行更新之前从触发器中禁用触发器,然后再重新启用它。
基本上,我有两张桌子:
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 行时,我应该在更新之前禁用触发器并在更新之后重新启用 - 但由于这是触发器,我无法更改触发器。 .
有什么想法吗?
编辑:我有一个想法,我可以设置一个全局变量并在我不想运行的触发器中检查这个 var 等 - 但不确定如何最好地实现?
【问题讨论】:
-
恕我直言,使用包变量是一个不错的选择。
-
@EgorSkriptunoff 你能在包中存储触发器吗?这将如何运作?
-
变量应该存储在一个包中。
-
不,您不能将触发器存储在一个包中,但您的面前应该有闪烁的警告。禁用触发器内的触发器永远不是正确的选择,您得到的错误表明没有正确规范化的数据库。 @Egor 建议您从触发器中删除所有逻辑并将其放在一个包中,这通常是解决此错误的方法。
-
您在这里做了两件不受欢迎且通常不受欢迎的事情:将触发器用于除审计活动之外的任何事情,以及存储冗余数据(即反规范化)。
标签: database oracle plsql triggers