我想出了以下触发器来提取执行表行更新语句时更新的所有列名...
但问题是如果有更多列(至少100列),性能/效率就会受到关注
示例触发器代码:
set define off;
create or replace TRIGGER TEST_TRIGG
AFTER UPDATE ON A_AAA
FOR EACH ROW
DECLARE
mytable varchar2(32) := 'A_AAA';
mycolumn varchar2(32);
updatedcols varchar2(3000);
cursor s1 (mytable varchar2) is
select column_name from user_tab_columns where table_name = mytable;
begin
open s1 (mytable);
loop
fetch s1 into mycolumn;
exit when s1%NOTFOUND;
IF UPDATING( mycolumn ) THEN
updatedcols := updatedcols || ',' || mycolumn;
END IF;
end loop;
close s1;
--do a few things with the list of updated columns
dbms_output.put_line('updated cols ' || updatedcols);
end;
/
有没有其他方法可以获取清单?
可能使用v $ tables(v $ transaction或类似的东西)?
答案 0 :(得分:0)
不是通过UPDATED
UPDATING()
列的最佳方法
你可以像这样使用隐式游标来改变你的代码,它会更快一点
set define off;
create or replace TRIGGER TEST_TRIGG
AFTER UPDATE ON A_AAA
FOR EACH ROW
DECLARE
updatedcols varchar2(3000);
begin
for r in (select column_name from user_tab_columns where table_name ='A_AAA')
loop
IF UPDATING(r.column_name) THEN
updatedcols := updatedcols || ',' || r.column_name;
END IF;
end loop;
dbms_output.put_line('updated cols ' || updatedcols);
end;
/
答案 1 :(得分:0)
面对类似的任务,我们最终编写了一个pl / sql过程,列出了表的列,为我们生成完整的触发器体,静态代码引用:new.col
和:old.col
。这种触发器的执行应该更快(尽管我们没有比较)。
然而,缺点是,当您稍后向表中添加新列时,很容易忘记更新触发器主体。它可能以某种方式通过监视工作或其他方式进行管理,但现在它对我们有用。
P.S。我对updating('COL')
功能的作用感到好奇,并立即进行了检查。我发现如果列在update
语句中,它返回true,即使列的值实际上没有改变(:old.col
等于{ {1}})。如果通过类似Java Hibernate库的方式更新表,则可能会生成不需要的历史记录,这些库(默认情况下)始终指定它生成的更新语句中的所有列。在这种情况下,您可能希望实际比较触发器主体内部的值,并仅在新值与旧值不同时插入历史记录。