是否更新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(表DEVICE正在变化,触发器/函数可能看不到列表(:

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;

也许我不能在这里使用触发器,因为修改触发触发器的同一对象在行级触发器中不能被修改或读取?以某种方式使用预定的作业更好吗?

我还想做的是,如果设备的STATUS变回0,则将FLAG_LIST更新回1。我能想象的唯一方法也是在触发器中,但正如我所写的,我不确定这是否基本上是可能的。

提前谢谢!

device上的行级触发器无法查询device表。不过,我的赌注是,您不需要也可以简单地使用:new伪记录(注意,考虑到if语句,子查询中的:new.status谓词在这里是多余的,但不会对任何内容造成任何损害(

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等的查询,则不会遇到问题。

最新更新