我偶然发现我需要在执行更新之前从触发器中禁用触发器,然后将其重命名。
基本上,我有两张桌子:
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等等 - 但不确定如何最好地实现?答案 0 :(得分:4)
您几乎可以肯定使用EXECUTE IMMEDIATE
语句禁用另一个触发器:
EXECUTE IMMEDIATE 'ALTER TRIGGER trigger_name_here DISABLE';
但是,您绝对不应该使用触发器来应用程序逻辑。这是一个混乱的业务,尤其是因为触发器不能保证按顺序触发,而且还因为你遇到的那种“问题”。
将所有所描述的功能移动到存储过程或包中会更容易,也更安全,并且只在必要时才使用触发器进行验证。
答案 1 :(得分:0)
当您必须自定义现有功能并且您只能完全控制数据库时,会出现这类问题。因此,您无法通过过程替换插入/更新,您可以做出反应。在这种情况下,您在两个表上都有触发器,并在两个方向上在表之间传播值。