oracle - Oracle 中触发器或计划作业中的更新语句?
问题描述
如果设备的状态发生更改,我想更新某些行。这是简单的更新语句:
update REMINDER set FLAG_LIST = 0 where ID in
(select r.id from REMINDER r
join DEVICE d
on d.id = (regexp_replace(r.origin_values, '[^0-9]', ''))
and d.status <> 0
and r.context = 'DEVICE'
and r.flag_list <> 0);
我写了一个如下所示的触发器,但是当我更改设备的状态时,我得到一个 ORA-04091(表设备正在变异,触发器/函数可能看不到 ist):
create or replace TRIGGER DEACTIVATE_REMINDER
AFTER UPDATE OF STATUS ON DEVICE
for each row
BEGIN
if updating then
if (:old.STATUS = 0 and :new.STATUS != 0) then
update REMINDER set FLAG_LIST = 0 where ID in
(select r.ID from REMINDER r
join DEVICE d
on d.id = (regexp_replace(r.ORIGIN_VALUES, '[^0-9]', ''))
and d.STATUS <> 0
and d.ID = :new.ID
and r.CONTEXT = 'DEVICE'
and r.FLAG_LIST <> 0);
end if;
end if;
END;
也许我不能在这里使用触发器,因为不能在行级触发器中修改或读取其修改触发触发器的同一对象?以某种方式使用预定的工作会更好吗?
我还想做的是更新FLAG_LIST
回1
,如果STATUS
设备的更改回0
. 我能想到的唯一方法也是在触发器中,但正如我所写的,我不确定这是否基本上是可能的。
先感谢您!
解决方案
device
无法查询device
表的行级触发器。不过,我的赌注是,您不需要并且可以简单地使用:new
伪记录(请注意,:new.status
考虑到语句,子查询中的谓词在这里是多余的,if
但不会伤害任何东西)
create or replace TRIGGER DEACTIVATE_REMINDER
AFTER UPDATE OF STATUS ON DEVICE
for each row
BEGIN
if updating then
if (:old.STATUS = 0 and :new.STATUS != 0) then
update REMINDER set FLAG_LIST = 0 where ID in
(select r.ID
from REMINDER r
where :new.id = (regexp_replace(r.ORIGIN_VALUES, '[^0-9]', ''))
and :new.STATUS <> 0
and r.CONTEXT = 'DEVICE'
and r.FLAG_LIST <> 0);
end if;
end if;
END;
如果这不是您想要的,提供一个完整的测试用例会很有帮助,我们可以运行它来查看您想要的行为。您可以创建一个复合触发器,其中包含一个将修改后的id
值存储在集合中的行级组件,然后是一个使用该集合更新表的语句级组件。但在这种情况下,这似乎有点矫枉过正。
然而,在架构上,我总是对将这种逻辑置于触发器中的设计犹豫不决。device
实际上,拥有一个更新表然后在表上运行您想要的任何更新的存储过程总是更有意义reminder
。您无需担心变异表异常,所有逻辑都将在一个地方,而不是部分在应用程序中,部分在触发器中,如果两个月后您想创建一个,您将不会遇到问题在reminder
涉及查询device
等的表上触发。