我已经想出了下面的触发器来提取所有的列名,这些列名在执行表行更新语句时被更新。
但问题是,如果有更多的列(至少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或类似的东西)?
2条答案
按热度按时间a6b3iqyw1#
不,这是通过
UPDATING()
获取UPDATED
列的最佳方法你可以像这样使用隐式游标来修改代码,这样会快一点
字符串
pengsaosao2#
面对类似的任务(对表行进行审计修改),我们最终编写了一个pl/sql过程,它列出了表的列,并为我们生成了完整的触发器体,静态代码引用了
:new.col
和:old.col
。这样的触发器的执行可能会更快(尽管我们没有比较)。然而,缺点是当你以后向表中添加一个新列时,很容易忘记更新触发器体。它可能可以通过监视作业或其他方式进行管理,但现在它对我们来说是有效的。
P.S.我开始好奇
updating('COL')
功能是做什么的,现在检查了一下。我发现如果列存在于update
语句中,即使列的 value 实际上没有改变,它也会返回true(:old.col
等于:new:col
)。这可能会生成不需要的历史记录,如果表被Java Hibernate库之类的东西更新,在这种情况下,您可能希望实际比较来自触发器主体内部的值,并仅在新值与旧值不同的情况下插入历史记录。