如何知道更新语句更新了哪些列?

时间:2014-10-20 09:22:33

标签: sql oracle triggers

我有一张简单的表格:

CREATE TABLE "TEST1" 
(
    "COLUMN1" VARCHAR2(20 BYTE), 
    "COLUMN2" CLOB, 
    "COLUMN3" RAW(16), 
    "COLUMN4" BLOB
)

现在我想编写一个监视更新的触发器,其中包含实际更改。

我试过了:

CREATE OR REPLACE TRIGGER "TEST1_TRIGGER1" 
AFTER UPDATE ON "TEST1" 
FOR EACH ROW 
begin
  dbms_output.put_line ('test1_trigger1');
  if :old.column1 <> :new.column1 then
    dbms_output.put_line ('column1 differs');
  end if;
  if :old.column2 <> :new.column2 then
    dbms_output.put_line ('column2 differs');
  end if;
  if :old.column3 <> :new.column3 then
    dbms_output.put_line ('column3 differs');
  end if;
  if :old.column4 <> :new.column4 then
    dbms_output.put_line ('column4 differs');
  end if;
  NULL;
END;

这会引发以下错误:

Error(16,19): PLS-00306: wrong number or types of arguments in call to '!='

问题在于Oracle无法比较BLOBS。

我该如何避免这个问题?如何知道更新更新的列?

2 个答案:

答案 0 :(得分:3)

您可以使用when updating predicate

...
begin
  dbms_output.put_line ('test1_trigger1');
  if updating ('column1') then
    dbms_output.put_line ('column1 differs');
  end if;
  if updating ('column2') then
    dbms_output.put_line ('column2 differs');
  end if;
  if updating ('column3') then
    dbms_output.put_line ('column3 differs');
  end if;
  if updating ('column4') then
    dbms_output.put_line ('column4 differs');
  end if;
end;

例如:

SQL> insert into test1 values ('A', 'B', 'AA', null);
SQL> update test1 set column1 = 'X', column2 = 'Y', column3 = 'FF';

test1_trigger1
column1 differs
column2 differs
column3 differs

答案 1 :(得分:2)

如果列包含在update语句中,WHEN UPDATING(column)谓词将返回TRUE,即使该值尚未实际更改。如果要监视实际更改,则可以使用提供的包:

CREATE OR REPLACE TRIGGER test1_trigger1
AFTER UPDATE ON test1
FOR EACH ROW 
begin
  if (  (:old.column1 is null and :new.column1 is not null)
     or (:old.column1 is not null and :new.column1 is null)
     or (:old.column1 <> :new.column1) )
  then
    dbms_output.put_line ('column1 differs');
  end if;
  if (  (:old.column2 is null and :new.column2 is not null)
     or (:old.column2 is not null and :new.column2 is null)
     or (dbms_lob.compare(:old.column2, :new.column2) <> 0) )
  then
    dbms_output.put_line ('column2 differs');
  end if;
  if (utl_raw.compare(:old.column3, :new.column3) <> 0) then
    dbms_output.put_line ('column3 differs');
  end if;
  if (  (:old.column4 is null and :new.column4 is not null)
     or (:old.column4 is not null and :new.column4 is null)
     or (dbms_lob.compare(:old.column4, :new.column4) <> 0) ) then
    dbms_output.put_line ('column4 differs');
  end if;
end;