我有一个带有相应 AFTER UPDATE 触发器的表,用于更改审计(Oracle 11g)。待审计表Test01:
CREATE TABLE Test01
(
Name Varchar2(40),
Surname Varchar2(40)
);
和表 History01 用于审计更改
CREATE TABLE History01
(
Old_val Varchar2(40),
New_val Varchar2(40),
Changed_col Varchar2(40)
);
当我使用带有 :old 和 :new 别名的列名时,它可以正常工作,例如:
create or replace TRIGGER trg_history01
AFTER UPDATE ON Test01
FOR EACH ROW
BEGIN
if :new.Name != :old.Name or ( :old.Name is NULL and :new.Name is not NULL ) then
INSERT INTO History01 VALUES (:old.Name, :new.Name, 'Name');
if :new.Surname != :old.Surname or ( :old.Surname is NULL and :new.Surname is not NULL ) then
INSERT INTO History01 VALUES (:old.Surname, :new.Surname, 'Surname');
end if
end if;
END;
Test01 可以包含更多列,因此我想遍历所有列而不是使用列名。但我不知道该怎么做,因为以下代码不起作用(无法编译):
create or replace TRIGGER trg_history01
AFTER UPDATE ON Test01
FOR EACH ROW
DECLARE
v_old varchar2(255);
v_new varchar2(255);
-- col_names contains all column names from table Test01
CURSOR col_names
IS
( SELECT column_name FROM USER_TAB_COLUMNS
WHERE LOWER(table_name) = 'test01' );
BEGIN
for col in col_names LOOP
-- save column name into variable
col_name := col.column_name;
-- to use it with OLD and NEW aliases, but followig two lines cause error "Bad bind variable"
v_old := :OLD.col_name;
v_new := :NEW.col_name;
if v_old != v_new or ( v_old is NULL and v_new is not NULL ) then
INSERT INTO History01 VALUES ( v_old, v_new, col_name);
end if;
END LOOP;
END;
有没有办法做到这一点,或者我总是必须使用列名?