Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Usenet -> c.d.o.misc -> Re: ORA-04091 - Mutating table
A copy of this was sent to nwilson_at_bdsinc.com (Ned Wilson) (if that email address didn't require changing) On Sat, 27 Jun 1998 13:47:14 -0400, you wrote:
>Good afternoon.
>
>I have run into the venerable mutating tables error, and I have been on
>the internet and read the documentation, and fixed the problem. When I
>changed the trigger so that it no longer referenced the table being
>updated, it caused another problem with our employee timesheets. So, I
>had to put the code back into place, mutating tables be damned.
>
>What I am trying to do is this: I simply want to do a select count(*)
>statement to count the number of records matching several constraints.
>Unfortunately, this table is in the process of being updated by yet
>another trigger, hence the mutate table error.
>
>Is there a way to tell if the offending trigger has completed firing, and
>committed its changes? If not, is there a PL/SQL equivalent of the sleep
>command? If there was a way to make the select statement wait until all
>previous modifications are complete, it would make my life a whole lot
>easier.
>
>Thanks in advance.
>
>
>Ned Wilson
>In-House Developer
>Business Data Services, Inc.
Here is the general purpose way to do this... This is an update example (eg: don't keep rowids of deleted rows, they won't exist in the AFTER DELETE trigger if you are processing a DELETE trigger). for your needs, you need to keeps pl/sql tables of the deleted values (you might for example need 2 tables -- one for A and one for B or you could use a table of records, whatever).
The concept is this--
a FOR EACH ROW Trigger will capture the values into pl/sql tables. An AFTER trigger, which can read/write to the affected table or child tables (if its declaritive RI that is the issue).
We need to implement
Here is an example:
create or replace package emp_pkg
as
type ridArray is table of rowid index by binary_integer;
rids ridArray;
empty ridArray;
cnt number;
end;
/
create or replace trigger emp_bu
before update on emp
begin
emp_pkg.cnt := 0;
end;
/
create or replace trigger emp_aufer
after update on emp
for each row
begin
emp_pkg.cnt := emp_pkg.cnt + 1;
emp_pkg.rids( emp_pkg.cnt ) := :new.rowid;
end;
/
create or replace trigger emp_au
after update on emp
declare
avg_sal number;
begin
for i in 1 .. emp_pkg.cnt loop
select avg(sal) into avg_sal from emp where deptno = ( select deptno from emp where rowid = emp_pkg.rids(i) ); -- do something about it..... dbms_output.put_line( emp_pkg.rids(i) || ' avg = ' || avg_sal );end loop;
update emp set ename = upper(ename);
Thomas Kyte
tkyte_at_us.oracle.com
Oracle Government
Herndon VA
http://govt.us.oracle.com/ -- downloadable utilities
Anti-Anti Spam Msg: if you want an answer emailed to you, you have to make it easy to get email to you. Any bounced email will be treated the same way i treat SPAM-- I delete it. Received on Sat Jun 27 1998 - 00:00:00 CDT
![]() |
![]() |