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

guicsvcw  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(149)

我已经想出了下面的触发器来提取所有的列名,这些列名在执行表行更新语句时被更新。
但问题是,如果有更多的列(至少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或类似的东西)?

a6b3iqyw

a6b3iqyw1#

不,这是通过UPDATING()获取UPDATED列的最佳方法
你可以像这样使用隐式游标来修改代码,这样会快一点

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;
/

字符串

pengsaosao

pengsaosao2#

面对类似的任务(对表行进行审计修改),我们最终编写了一个pl/sql过程,它列出了表的列,并为我们生成了完整的触发器体,静态代码引用了:new.col:old.col。这样的触发器的执行可能会更快(尽管我们没有比较)。
然而,缺点是当你以后向表中添加一个新列时,很容易忘记更新触发器体。它可能可以通过监视作业或其他方式进行管理,但现在它对我们来说是有效的。
P.S.我开始好奇updating('COL')功能是做什么的,现在检查了一下。我发现如果列存在于update语句中,即使列的 value 实际上没有改变,它也会返回true(:old.col等于:new:col)。这可能会生成不需要的历史记录,如果表被Java Hibernate库之类的东西更新,在这种情况下,您可能希望实际比较来自触发器主体内部的值,并仅在新值与旧值不同的情况下插入历史记录。

相关问题