Home » SQL & PL/SQL » SQL & PL/SQL » Mutating table problem (from trigger)
Mutating table problem (from trigger) [message #9174] Fri, 24 October 2003 09:36 Go to next message
Mark Grimshaw
Messages: 73
Registered: June 2002
Member
Hi,

I am getting the error "ORA-04091 table is mutating, table or function may not see it" error.

What I am trying to do is on the deletion of a record from a table, I want to delete another record.

For simplicity, here is a stripped down version of the relevant table: -

Table: Run
----------

RunNumber number,
Testname varchar2(10)

Let's say I have 3 records in this table: -

Testname RunNumber
-------- ---------
DA1F 1
DA1C 1
DA1B 1

What I want to be able to do is on the deletion of a Run record with a Testname appended with an "F" or "D"
is to delete the record with the "C" appended Testname, i.e. on deletion of Run with 'DA1B' or 'DA1F' delete Run with 'DA1C'.

I get the mutation error if the trigger is implemented either as a 'before or 'after' trigger.

I have done some searching on the web for possible solutions and it appears that what I am trying to do is not possible. I also don't see how I could use a Declarative Integrity rule in this case. A re-design is also out of the question. What are my options, if any?

TYIA

Mark Grimshaw
Re: Mutating table problem (from trigger) [message #9183 is a reply to message #9174] Fri, 24 October 2003 12:44 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
sql>select * from run;
 
RUNNUMBER TESTNAME
--------- ----------
        1 DA1F
        1 DA1C
        1 DA1B
        2 ABCF
        2 ABCC
        2 ABCB
 
6 rows selected.
 
sql>create or replace package pkg_run
  2  is
  3    type array is table of run.runnumber%type index by binary_integer;
  4    v_array  array;
  5  
  6    procedure process;
  7  
  8  end;
  9  /
 
Package created.
 
sql>create or replace package body pkg_run
  2  is
  3  
  4    procedure process
  5    is
  6    begin
  7      for i in 1..v_array.count loop
  8        delete
  9          from run
 10         where runnumber = v_array(i)
 11           and testname like '%C';  -- or substr(testname, 4, 1) = 'C' if fixed width
 12      end loop;
 13    end;
 14  
 15  end;
 16  /
 
Package body created.
 
sql>  create or replace trigger run_bds
  2    before delete on run
  3  begin
  4    pkg_run.v_array.delete;
  5  end;
  6  /
 
Trigger created.
 
sql>create or replace trigger run_ad
  2    after delete on run
  3    for each row
  4    when (old.testname like '%F' or old.testname like '%B')
  5  begin
  6    pkg_run.v_array(pkg_run.v_array.count + 1) := :old.runnumber;
  7  end;
  8  /
 
Trigger created.
 
sql>create or replace trigger run_ads
  2    after delete on run
  3  begin
  4    pkg_run.process;
  5  end;
  6  /
 
Trigger created.
 
sql>delete from run where runnumber = 1 and testname = 'DA1F';
 
1 row deleted.
 
sql>select * from run where runnumber = 1;
 
RUNNUMBER TESTNAME
--------- ----------
        1 DA1B
 
1 row selected.
 
sql>delete from run where runnumber = 2 and testname = 'ABCB';
 
1 row deleted.
 
sql>select * from run where runnumber = 2;
 
RUNNUMBER TESTNAME
--------- ----------
        2 ABCF
 
1 row selected.
 
sql>select * from run;
 
RUNNUMBER TESTNAME
--------- ----------
        1 DA1B
        2 ABCF
 
2 rows selected.
Re: Mutating table problem (from trigger) [message #9203 is a reply to message #9183] Mon, 27 October 2003 02:07 Go to previous messageGo to next message
Mark Grimshaw
Messages: 73
Registered: June 2002
Member
Todd,

Thanks for the reply. A very neat solution (which I am just about to try). One question however is how is it guaranteed that the trigger run_ads is executed after run_ad? Is it to do with the order in which the triggers are actually created?

One again, thank you.

Mark Grimshaw
Re: Mutating table problem (from trigger) [message #9212 is a reply to message #9183] Mon, 27 October 2003 07:12 Go to previous messageGo to next message
Mark Grimshaw
Messages: 73
Registered: June 2002
Member
Todd,

It has been discovered that the required behaviour of the trigger is slightly different to what I described in my original posting. Apparently, it is necessary for me to do a search on the table in which the trigger is executing to establish whether certain records exist in the table. This is not possible is it?

To explain a little further. let's say that the trigger fires for a testname of say 'DA1F'. I am now required to do a search to see whether any records with testname's of 'DA1B' exist and if they don't then I am required to delete the record with the testname of 'DA1C'. To find out whether 'DA1B' testname'es exist in this case there is no other way but to do a search on the table.

Am I well and truly stuck now?

Mark
Re: Mutating table problem (from trigger) [message #9215 is a reply to message #9203] Mon, 27 October 2003 11:36 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
The firing order is guaranteed because the triggers are of different types. AD is an after-row trigger which is guaranteed to fire before ADS, an after-statement trigger.
Re: Mutating table problem (from trigger) [message #9216 is a reply to message #9212] Mon, 27 October 2003 11:53 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
Is the whole process initiated now by just a delete of an 'F' row? The example I gave was triggered by either a 'F' or 'B' row.

If just an 'F' delete should kick off the check, and the check is: Delete the corresponding 'C' row only if the corresponding 'B' row does not exist, then:

1) Change the AD trigger to only fire on a delete of an 'F' row:

when (old.testname like '%F')


2) Change the SQL in the package to:

delete  
  from run r1
 where runnumber = v_array(i) 
   and testname like '%C'
   and not exists (select null
                     from run r2
                    where r2.runnumber = r1.runnumber
                      and testname like '%B');
Re: Mutating table problem (from trigger) [message #9217 is a reply to message #9216] Mon, 27 October 2003 11:54 Go to previous messageGo to next message
Todd Barry
Messages: 4819
Registered: August 2001
Senior Member
where r2.runnumber = r1.runnumber
  and <b>r2.</b>testname like '%B');
Re: Mutating table problem (from trigger) [message #9241 is a reply to message #9216] Tue, 28 October 2003 08:42 Go to previous messageGo to next message
Mark Grimshaw
Messages: 73
Registered: June 2002
Member
Todd,

I was finally handed the full requirements of the job required. I then spent over a day working with the techniques you provided me with and finally managed to get the required behaviour - so many thanks. the thing that caused so many problems was that Oracle does not complain when you use an index table (specified with the index by BINARY_INTEGER cluase) with a record type. It became apparant that not only did I need to store just the run number in the 'temp' table but also the TestnameID. I kept getting the Oracle 'NOT DATA FOUND' error when executing the SQL query you provided me with. This was because although the Run Number was stored successfully in each collection element of the table the Testname ID wasn't. Yet Oracle didn't complain when I did something like the following: -

v_array(count + 1).RunNumber := :old.RunNumber;
** v_array(count + 1).TestnameID := :old.TestnameID;

The second line was allowed but I don't have a clue where the testnameid goes?

In any case, I now use the less elegant Nested Table which I have to extend manually.

One again, thanks.
Re: Mutating table problem (from trigger) [message #9251 is a reply to message #9215] Wed, 29 October 2003 06:43 Go to previous message
Mark Grimshaw
Messages: 73
Registered: June 2002
Member
Todd,

I was just wondering whether the solution that you originally came up with could handle deletion queries like this: -

delete from run where testname like 'D%' ?

I thought that everything was ok until I did the above query and I then got the 'ORA-06533 Subscript beyond count' error.

I have tried to find out what is going wrong with my version but to no avail.

Mark
Previous Topic: need query to fetch data in specific format
Next Topic: eplainplan
Goto Forum:
  


Current Time: Fri May 10 15:07:10 CDT 2024