Oracle 在更新后触发器上获取更新列名的有效方法
我使用了以下触发器来提取执行表行更新语句时更新的所有列名 但问题是如果有更多的列(至少100列),性能/效率就会受到关注 触发代码示例:Oracle 在更新后触发器上获取更新列名的有效方法,oracle,plsql,cursor,database-trigger,Oracle,Plsql,Cursor,Database Trigger,我使用了以下触发器来提取执行表行更新语句时更新的所有列名 但问题是如果有更多的列(至少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 varch
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$表(v$事务或任何类似的)?否通过
更新()
您可以像这样使用隐式游标更改代码,这样会快一点
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;
/
面对类似的任务,我们最终编写了一个pl/sql过程,该过程列出了表中的列并为我们生成完整的触发器主体,其中静态代码引用了
:new.col
和:old.col
。这种触发器的执行速度应该更快(尽管我们没有进行比较)
但是,缺点是,当您稍后向表中添加新列时,很容易忘记更新触发器主体。它可能可以通过监控工作或其他方式进行管理,但目前它对我们有效
另外,我开始好奇那个
更新('COL')
功能是做什么的,现在检查了一下。我发现,如果列出现在update
语句中,即使列的值实际上没有更改(:old.col
等于:new:col
),它也会返回true。如果表由Java Hibernate library之类的东西更新,则这可能会生成不需要的历史记录,Java Hibernate library(默认情况下)总是指定它生成的update语句中的所有列。在这种情况下,您可能希望实际比较触发器主体内部的值,并仅在新值与旧值不同的情况下插入历史记录。您可以在更新触发器之前执行,并可以将:new.col
与“:old.col”进行比较,但首先,100 cols+听起来有点太多了。在ERP
系统中,标准化似乎是有害的,似乎每个表至少有40列。这可能不是因为标准化,或者ERP系统无法对用户自定义的表进行非标准化。。。只是一个想法…我的直觉是。。。如果oracle为更新('colname')
返回true,那么它必须在db transaction v$表中的某个位置具有更新列的列表(可能是隐藏的)。。。所以如果我们直接得到它,我们不需要遍历所有列(100列),如果更新是在单个列上完成的,那么您如何考虑尝试更新动态sql表达式,当您知道要更新哪些列时,您可以收集列名、值,然后通过动态sql构建insert语句,此时您知道哪些列正在更新?这只是在特定表上设置一个简单的审核。。。没别的了。。。这是为了提醒用户,她在桌子上做了哪些更改