在更新后触发器上获取更新列名的有效方法

时间:2017-06-02 09:03:33

标签: sql oracle triggers cursor

我想出了以下触发器来提取执行表行更新语句时更新的所有列名...

但问题是如果有更多列(至少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 个答案:

答案 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库的方式更新表,则可能会生成不需要的历史记录,这些库(默认情况下)始终指定它生成的更新语句中的所有列。在这种情况下,您可能希望实际比较触发器主体内部的值,并仅在新值与旧值不同时插入历史记录。