I have created a trigger on a table which holds an audit log. When a new entry is inserted I want to compare the new record with the latest existing record in the table (matching ID) column by column. If the value for one column has changed I want to execute an insert statement into another table. I have created the following PL SQL procedure:
CREATE OR REPLACE
TRIGGER PROJECT_BASELINE_ATTR_AUD_BI BEFORE INSERT
ON PROJECT_BASELINE_ATTR_AUD
FOR EACH ROW
DECLARE
tab_name constant varchar2(32) := 'PROJECT_BASELINE_ATTR_AUD';
col_name varchar2(32);
v_latest_row PROJECT_BASELINE_ATTR_AUD%rowtype;
BEGIN
-- get the record to compare with
EXECUTE IMMEDIATE 'select * from '||tab_name||
' where rev = (select max(rev) from '||tab_name||' where id = '|| :new.ID ||')' into v_latest_row;
FOR x IN (SELECT DISTINCT(COLUMN_NAME) FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = upper(tab_name))
LOOP
BEGIN
col_name := x.column_name;
-- do insert if the values are unequal
-- IF :new.col_name <> v_latest_row.col_name
-- INSERT INTO AUD_CHANGE_LOG VALUES (AUD_CHANGE_LOG_ID_SEQ.nextVal, :new.ID, :new.REV, tab_name, col_name);
END;
END LOOP;
END;
I know I could implement this with the real column name e.g.
IF :new.FOO <> v_latest_row.FOO
IF :new.BAR <> v_latest_row.BAR
...
but this would end up in a long if else cascade. Any ideas?
There is no way to refer new and old values of the trigger dynamically.
You may develop a system that dynamically defines a trigger for each table structure you need, but it’s a hard job anyway.
I did something like that and it’s not the kind of things you can finish in a couple of days.