UPDATE触发器之后-NEW和OLD列别名

时间:2019-12-29 10:27:23

标签: oracle plsql database-trigger audit journaling

我有一个表,该表带有用于更改审核的相应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;

有没有一种方法或者我总是必须使用列名?

0 个答案:

没有答案
相关问题