Re: Is there a workaround for the 'mutating table' problem in a trigger ?

From: Thomas J Kyte <tkyte_at_us.oracle.com>
Date: 1996/04/12
Message-ID: <4klq6f$cv3_at_inet-nntp-gw-1.us.oracle.com>#1/1


coolcat_at_citynet.net wrote:

>Hi
 

>In a trigger on a table, I want to do a
>SELECT MAX() ...
>from that table and update a denormalized column in another table.
 

>However, the table obviously mutates.

Hopefully, the following example is similar enough to your case. In short, what you do is capture enough information in a for each row trigger (eg: the primary key or part of the primary key) in order to do the processing in an AFTER trigger. For example, t1 has a multi-part primary key (a,b). We want to keep the maximum value of B for a given value of A in another table t2. Here is what you might code:

create table t1

(	a	number,
	b	number,
	c	number,
	constraint t1_pk primary key(a,b)

)
/

create table t2

( 	a	number,
	max_b	number,
	constraint t2_pk primary key(a,max_b)

)
/

create or replace package t1_pkg
as

	type Array is table of t1.a%type index by binary_integer;
	arr	Array;
	empty	Array;
	cnt	number;

end t1_pkg;
/

create or replace trigger t1_bui
before update or insert on t1
begin

	t1_pkg.cnt := 0;
	t1_pkg.arr := t1_pkg.empty;

end;
/

create or replace trigger t1_auifer
after update or insert on t1 for each row begin

	t1_pkg.cnt := t1_pkg.cnt + 1;
	t1_pkg.arr( t1_pkg.cnt ) := :new.a;

end;
/

create or replace trigger t1_aui
after update or insert on t1
begin

	for i in 1 .. t1_pkg.cnt loop
		update t2 
		   set max_b = ( select max(b) from t1 where a = t1_pkg.arr(i) )
		 where a = t1_pkg.arr(i);
		if ( sql%rowcount = 0 ) then
			insert into t2 
			select a, max(b) 
			  from t1 
			 where a = t1_pkg.arr(i)
			 group by a;
		end if;
	end loop;

end;
/

BTW: bui = before update insert

     auifer = after update insert for each row
     aui = after update insert.

It's just a naming convention and nothing special.

>I understand SYBASE has a workaround using which you can do a SELECT
>on the table on which the trigger is defined.

They only have one trigger firing point, the equivalent of our AFTER INSERT or UPDATE trigger. From there you can select on the table, just as you can in Oracle.

>Does ORACLE ?

Yes.

>TIA.
Thomas Kyte
tkyte_at_us.oracle.com
Oracle Government



opinions and statements are mine and do not necessarily reflect the opinions of Oracle Corporation. Received on Fri Apr 12 1996 - 00:00:00 CEST

Original text of this message