Oracle PL / SQL Запуск до / после ОБНОВЛЕНИЯ, чтобы идентифицировать ТОЛЬКО столбцы, которые были изменены в таблице - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь разработать триггер для сбора сведений об обновлении таблицы - TEST_TABLE. Я создал таблицу аудита для сбора деталей, но мне нужен какой-то способ, чтобы получить ТОЛЬКО измененный столбец и старые / новые значения. Написали процедуру CHECK_VAL для проверки на разницу и курсор для перебора всех имен столбцов, объединенных псевдостолбцами ": NEW" и ": OLD".

create or replace PROCEDURE CHECK_VAL( 
    L_NEW IN VARCHAR2,
    L_OLD IN VARCHAR2,
    LC_IS_DIFF out varchar2)
IS
BEGIN
    DBMS_OUTPUT.PUT_LINE('IN PROC CHECK_VAL : NEW_VAL '||L_NEW||' OLD: '||L_OLD);

    IF ( L_NEW <> L_OLD OR
        (L_NEW IS NULL AND L_OLD IS NOT NULL) OR
        (L_NEW IS NOT NULL AND L_OLD IS NULL) )
    THEN
         DBMS_OUTPUT.PUT_LINE('IN PROC CHECK_VAL IF');
         LC_IS_DIFF := 'YES';
    ELSE 
         lc_is_diff := 'NO';
    END IF;
END;

/ ************* /

 create or replace trigger xxtest
    before update on test_table
    for each row
    declare
        ln_cnt number := 0;
        lc_new varchar2(50);
        lc_old varchar2(50);

        lc_col varchar2(50);
        lc_stat varchar2(50);
        cursor lcu_c1 (p_tbl_name varchar2)
        is 
            select column_name
            from user_tab_columns
            where table_name = p_tbl_name;
        lc_column lcu_c1%rowtype;
    begin
        for lc_column in lcu_c1('TEST_TABLE')
        loop
            dbms_output.put_line('In loop ');
            lc_col := lc_column.column_name;
            lc_new := ':NEW.' || lc_col;
            lc_old := ':OLD.' || lc_col;
            check_val(lc_new,lc_old,lc_stat);
            dbms_output.put_line('Column '||lc_col);
            dbms_output.put_line('Changed? '||lc_stat);
            if lc_stat = 'YES' then
                insert into audit_tbl values (sysdate,lc_col);
            end if;
        end loop;
        dbms_output.put_line('Exit trigger');
    end;

/ ********** /

update test_table
set col2= 'DX'
where col1= 'A';

После запуска обновления таблицы - TEST_TABLE, вывод выглядит следующим образом. Существует проблема, потому что o / p для ': NEW. || lc_col1' в основном представляет собой строку с ': NEW.column1' INSTEAD из значение: NEW.col1. Любая помощь будет оценена. Спасибо.!

Вывод: -

"
1 row(s) updated.
In loop 
IN PROC CHECK_VAL : NEW_VAL :NEW.COL1 OLD: :OLD.COL1
IN PROC CHECK_VAL IF
Column COL1
Changed? YES
In loop 
IN PROC CHECK_VAL : NEW_VAL :NEW.COL2 OLD: :OLD.COL2
IN PROC CHECK_VAL IF
Column COL2
Changed? YES
In loop 
IN PROC CHECK_VAL : NEW_VAL :NEW.COL3 OLD: :OLD.COL3
IN PROC CHECK_VAL IF
Column COL3
Changed? YES
Exit trigger
"

1 Ответ

0 голосов
/ 04 марта 2020

Вы передаете строки ': NEW.columnname' и ': OLD.columnname' в процедуру check_val. Затем вы проверяете, отличаются ли эти строки, которые, конечно, всегда есть (одна имеет «NEW» как символы 2,3 и 4, а другая «OLD»).

То, что вы должны передать значения в переменных: NEW.columnname и: OLD.column_name.

...