触发新旧列

时间:2009-12-07 10:57:15

标签: sql oracle plsql triggers oracle10g

为什么我们不能在语句级触发器中使用:new和:old列?

3 个答案:

答案 0 :(得分:6)

因为语句可能是插入/删除/更新多行的情况。因此,没有列。

示例:

update FOO set a = 12 where b = 9;

或者:

delete from FOO where b = 9;

或者:

insert into FOO (a, b) select 12, x from BAR;

如果 FOO 表有一个语句触发器,则在这三个句子中无法判断您是在无行,单行还是多行操作。

答案 1 :(得分:4)

因为DML可能是基于集合的,所以会影响表中的多行。事实上,由于SQL是基于正确设置的,应该是通常的情况。因此,语句级别触发器无法确定哪个:OLD以及哪个:您指的是新值。

答案 2 :(得分:0)

如上所述,语句级别触发器可以进行一到多行更改,因此:new和:old不可用。

如果需要跟踪:new和:old值并需要在语句触发器上访问它们,则可以创建行级触发器,该触发器存储新值和旧值以供语句级别使用。这是我们在

之前解决这个问题的一种方法

包裹:

create or replace package table_trigger_helper is

  subtype subtype_rowtype is table_name$rowtype;
  type table_rowtype is table of subtype_rowtype;

  v_old table_rowtype := table_rowtype();
  v_new table_rowtype := table_rowtype();

end table_trigger_helper;
/

行级别触发器:

create or replace trigger row_level_trigger_name
  after insert or delete or update
  on table_name
  for each row
declare

  r_old table_trigger_helper.table_rowtype := NULL;
  r_new table_trigger_helper.table_rowtype := NULL;
  i pls_integer;

begin

 if update or deleting then
  r_old.column_one := :old.column_one
  ...
 end if;

 if update or inserting then
  r_new.column_one := :new.column_one
 end if;

  table_trigger_helper.v_old.extend();
  table_trigger_helper.v_new.extend();
  i := table_trigger_helper.v_old.last;

  table_trigger_helper.v_old( i ) := r_old;
  table_trigger_helper.v_new( i ) := r_new;  
end row_level_trigger_name;
/  

声明级别触发器:

create or replace trigger statement_level_trigger_name
 after insert or delete or update
 on table_name
declare
begin
  --process through your new and old records;
  --table_trigger_helper.v_old
  --table_trigger_helper.v_new
end statement_level_trigger_name;
/