Jedna možnost:Zatlačte na logiku, abyste zkontrolovali, zda je sloupec sledován do procedury f_log, a poté proveďte přes všechny sloupce.
Pokud například vaše track_Table obsahuje (table_name, column_name, allow) hodnoty pro každý sloupec, který chcete sledovat, pak něco takového
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;
A pro dobro, umístěte hodnoty ve vaší track_table na insert velkými písmeny, abyste nemuseli UPPER() uložené hodnoty, takže jakýkoli index na těchto hodnotách bude zbytečný!
Nyní to bude žvýkat některé zdroje kontrolující název každého sloupce u každé operace, ale pokud nepoužíváte velké objemy, mohlo by to být zvládnutelné.
Jinak budete potřebovat elegantnější řešení. Jako využití síly kolekcí a klauzule TABLE() k provedení vyhledávání track_table v hromadné operaci. Mějte na paměti, že jsem v tuto chvíli mimo svou databázi, takže jsem tento kód nezkompiloval.
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;
/