sql >> データベース >  >> RDS >> Oracle

トリガー内の動的操作にOLDおよびNEWオブジェクトを使用する

    1つのオプション:ロジックをプッシュして、列がf_logプロシージャに追跡されているかどうかを確認してから、すべての列に渡します。

    たとえば、track_Tableが追跡する各列の(table_name、column_name、allow)値を保持している場合、次のようになります

     CREATE OF REPLACE PROCEDURE f_log(  p_id          varchar2  
                                        ,p_table_name  varchar2
                                        ,p_column_name varchar2
                                        ,p_old_val     varchar2
                                        ,p_new_val     varchar2)
     as
        l_exists number;
        cursor chk_column_track IS
            SELECT  1
            FROM    track_TABLE           
            WHERE   upper(TABLE_NAME)  = upper(p_table_name)              
            AND     UPPER(column_name) = upper(p_column_name)
            AND     upper(allow) = 'Y'; 
     begin
        open chk_column_track;
        fetch chk_column_track into l_exists;
        if chk_column_track%found then
           --do the insert here
        end if;
        close chk_column_track;
     end;
     /
    
     CREATE OR REPLACE TRIGGER trg_TRACK 
     AFTER INSERT OR UPDATE OR DELETE ON ABC 
     FOR EACH ROW 
     DECLARE   
          n_id varchar(50); 
     BEGIN   
        n_id := NVL(:old.id, :new.id);   
        -- send all of the values to f_log and have it decide whether to save them
        f_log(:old.id,'COL1',:old.col1,:new.col1);   
        f_log(:old.id,'COL2',:old.col2,:new.col2);   
        f_log(:old.id,'COL3',:old.col3,:new.col3);   
        ... 
     END; 
    

    また、念のため、挿入時にtrack_tableの値を大文字にして、格納されている値をUPPER()する必要がないようにします。これにより、これらの値のインデックスが役に立たなくなります。

    これで、各操作で各列名をチェックするいくつかのリソースが消費されますが、大量に実行していない場合は、管理しやすい可能性があります。

    それ以外の場合は、よりエレガントなソリューションが必要になります。コレクションの力とTABLE()句を利用して、一括操作でtrack_tableルックアップを実行するのと同じです。現在、データベースから離れているため、このコードをテストコンパイルしていないことに注意してください。

        CREATE OR REPLACE TYPE t_audit_row AS OBJECT (
       p_table_name   varchar2(30)
      ,p_column_name  varchar2(30)
      ,p_id           varchar2(50)
      ,p_old_val      varchar2(2000)
      ,p_new_val      varchar2(2000)
    );
    
    CREATE OR REPLACE TYPE t_audit_row_table AS TABLE OF t_audit_row;
    
    CREATE OR REPLACE PROCEDURE f_log (p_audit_row_table t_audit_Row_table)
    AS
    begin
       -- see how we can match the contents of the collection to the values
       -- in the table all in one query. the insert is just my way of showing
       -- how this can be done in one bulk operation. Alternately you could make
       -- the select a cursor and loop through the rows to process them individually.
       insert into my_audit_log (table_name, column_name, id, old_val, new_val)
       select  p_table_name
              ,p_column_name
              ,p_id
              ,p_old_val
              ,p_new_val
       FROM   track_TABLE TT
             ,table(p_audit_row_table) art
       WHERE  tt.TABLE_NAME   = art.p_table_name                       
       AND    tt.column_name  = art.p_column_name         
       AND    tt.allow        = 'Y';
    end;
    /
    
    CREATE OR REPLACE TRIGGER trg_TRACK   
    AFTER INSERT OR UPDATE OR DELETE ON ABC   
    FOR EACH ROW   
    DECLARE          
      l_id           varchar(50);   
      l_audit_table  t_audit_row_table;
    BEGIN        
      l_id := NVL(:old.id, :new.id);        
      -- send all of the values to f_log and have it decide whether to save them   
      l_audit_table := t_audit_row_table (
                          t_audit_row ('ABC','COL1',l_id, :old.col1, :new.col1)  
                          ,t_audit_row ('ABC','COL2',l_id, :old.col2, :new.col2)  
                          ,t_audit_row ('ABC','COL3',l_id, :old.col3, :new.col3)  
                          ,...  
                          ,t_audit_row ('ABC','COLn',l_id, :old.coln, :new.coln)  
                       );
      f_log(l_audit_table);
    end;
    /
    


    1. Fuse6.3dbcp基本データソース

    2. 明示的結合と暗黙的結合?

    3. タイムゾーンをデータベースに保存する適切な方法は?

    4. PHPのWhileループでMySQLクエリを使用しないようにするにはどうすればよいですか?