我的要求是更新表中input_disp_req ='Y'的所有行的序列号,更新列 input_disp_req 时请帮我创建触发器。即使我在更新后使用过,我也会收到错误。
ORA-04091(表fce_template正在变异。触发器/函数可能看不到它)
CREATE OR REPLACE TRIGGER fce_trigger
AFTER UPDATE of input_disp_req ON fce_template
for each row
BEGIN
update fce_template
set pos_clmn = fce_seq.nextval
where region = :new.region
and mode_name = :new.mode_name
and input_disp_req = 'Y';
END;
如果有其他方法可以告诉我。请帮我。非常感谢提前:)
有3列input_disp_req,pos_clmn和pos_seq ...
所以我的要求是,当我将列input_disp_req中的值更新为N / Y触发器时应该 更新pos_seq排序的所有匹配行的列pos_clmn的序列值。
input_disp_req = Y表示根据我的要求,输入数据中存在该值。
答案 0 :(得分:2)
您可以尝试以下列方式使用复合触发器: 每行之后: 获取更新行的rowid或key列并将其放入pl / sql集合
声明后: 遍历所有行并更新序列
它应该摆脱“变异表”错误...
类似的东西(它可能缺少一些var声明):
create or replace trigger your_trigger
for update on your_table
compound trigger
--Trigger level variables so we capture all updates.
type t_rec is record(
flg varchar2(1));
type t_list_tab is table of t_rec index by pls_integer;
l_tab t_list_tab;
after each row is
l_new_the_id := :new.the_id;
l_old_the_id := :old.the_id;
if (not l_tab.exists(l_new_the_id)) then
l_cnt_tab(l_new_the_id).flg := '';
end if;
end after each row;
after statement is
if (l_tab.count != 0) then
for l_idx in l_tab.first .. l_tab.last loop
--your updates here
end loop;
end if;
end after statement;
end;
可能你只需要使用触发器,但每个人都只会告诉你你不应该 - 当你试图跟踪变化或发现错误时触发器会很痛苦 - 可能更好的方法是使用一个程序来更新表格,并使用其逻辑做所有的事情......
答案 1 :(得分:2)
让我们看看我是否能理解你的要求以及你迄今所做的评论......
似乎已经有一个列代表您的订单(您对DavidAldridge的评论)。我们假设它被称为order_col
。这样就可以按顺序检索记录:
select *
from fce_template
order by order_col;
您还可以获得“' Y'按顺序记录:
select *
from fce_template
where input_disp_req = 'Y'
order by order_col;
还有某个地区和模式:
select *
from fce_template
where region = :region
and mode_name = :mode_name
and input_disp_req = 'Y'
order by order_col;
但不知何故,这似乎还不够。您是否只想应用行号(在区域和模式内)?可以使用ROW_NUMBER:
完成select f.*, row_number() over (order by order_col) as pos_clmn
from fce_template f
where region = :region
and mode_name = :mode_name
and input_disp_req = 'Y'
order by order_col;
对于所有数据:
select
f.*,
row_number() over (partition by input_disp_req, region, mode_name
order by order_col) as pos_clmn
from fce_template f
where input_disp_req = 'Y'
order by order_col;
如果这是您想要的,您可以随时创建行号。你不必存储它们。存储它们甚至会很糟糕,因为你会引入冗余:订单将被提供两次,一次是order_col,一次是pos_clmn。别这么做。
答案 2 :(得分:1)
这不是答案。我只想说明你在做什么。
说你有这张桌子:
input_disp_req region mode_name pos_clmn some_data Y R1 M1 1 A Y R1 M1 2 B Y R1 M1 3 C N R1 M1 4 D N R1 M1 5 E
现在让我们来看看这个更新声明:
update fce_template set input_disp_req = 'Y' where input_disp_req = 'N';
这会更新两条记录,因此触发器会被触发两次。首次执行时,将有四条记录给序列号6到9。在第二次执行时,所有五个记录将为“Y”并获得序列号10到14.因此,在您更新后,您的记录可能如下所示:
input_disp_req region mode_name pos_clmn some_data Y R1 M1 14 A Y R1 M1 10 B Y R1 M1 12 C Y R1 M1 13 D Y R1 M1 11 E
你从中获得了什么?它似乎没有意义。您似乎正在使用错误的approch来实现您想要实现的目标。