Re: MUTATING PROBLEM !!! IN DATABASE TRIGGER

From: Thomas Kyte <tkyte_at_us.oracle.com>
Date: 1997/11/10
Message-ID: <3469263b.3854923_at_newshost>#1/1


[Quoted] On Sun, 09 Nov 1997 11:18:14 +0200, Isaac Chocron <itshak_at_hadassah.org.il> wrote:

>I intented to replace a phisical delete by a logical delete on my table
>T.
>I definided a Before delete trigger that performs:
>
>DECLARE
> NO_DELETE exception;
>Begin
> raise NO_DELETE;
>EXCEPTION
> when NO_DELETE then
> UPDATE T set HIDDEN_DATE = SYSDATE where rowid = :old.rowid;
>End;
>
>But I receive an ORA-04091: table T is mutating, trigger/function may
>not see it.
>
>A possible solution is to batch a database job, but I prefer a local
>solution to this error.
>
>Do you know another possible solution ?

Ok, I'll give you a 7.x solution and an 8.x solution (you don't mention the version you are using). For 8.x, the solution is pretty simple, it would look like this:

drop table delete_demo;

create table delete_demo ( a            int primary key,
                           b            date,
                           c            varchar2(10),
                           hidden_date  date );

create or replace view delete_demo_view as select a, b, c from delete_demo where hidden_date is null;

grant all on delete_demo_view to public;  

create trigger delete_demo_o8
instead of delete on delete_demo_view
for each row
begin

    update delete_demo set hidden_date = sysdate where a = :old.a; end;
/  



This shows off a new feature in o8, the instead of trigger. You can code triggers against views, letting you decide what to do for the action. In the above, we create a view that the world will use to insert/update/delete into the real table with. On this view, we create 'instead of' triggers when needed. Now we write the "instead of deleting do the update" logic you wanted.

insert into delete_demo_view values ( 1, sysdate, 'Hello' ); 1 row created.  

select * from delete_demo_view;  

         A B C
---------- --------- ----------

         1 10-NOV-97 Hello  

delete from delete_demo_view;
1 row deleted.  

select * from delete_demo_view;
no rows selected

select * from delete_demo;  

         A B C HIDDEN_DA ---------- --------- ---------- ---------

         1 10-NOV-97 Hello 10-NOV-97  



[Quoted] In version 7, we can't do this. The code to do the same thing in v7 is below:

drop table delete_demo;

create table delete_demo ( a            int primary key,
                           b            date,
                           c            varchar2(10),
                           hidden_date  date );
 

create or replace view delete_demo_view as select a, b, c from delete_demo where hidden_date is null; grant all on delete_demo_view to public;  

[Quoted] create or replace package delete_demo_pkg as

    type array is table of delete_demo%rowtype index by binary_integer;  

    oldvals array;
    cnt number;
end;
/    

create or replace trigger delete_demo_bd before delete on delete_demo
begin

    delete_demo_pkg.cnt := 0;
end;
/  

create or replace trigger delete_demo_bdfer before delete on delete_demo
for each row
declare

    i number default delete_demo_pkg.cnt+1; begin

    delete_demo_pkg.oldvals(i).a := :old.a;
    delete_demo_pkg.oldvals(i).b := :old.b;
    delete_demo_pkg.oldvals(i).c := :old.c;
    delete_demo_pkg.cnt := i;

end;
/  

create or replace trigger delete_demo_ad after delete on delete_demo
begin

    for i in 1 .. delete_demo_pkg.cnt loop

        insert into delete_demo ( a, b, c, hidden_date )
        values
        ( delete_demo_pkg.oldvals(i).a, delete_demo_pkg.oldvals(i).b,
          delete_demo_pkg.oldvals(i).c, sysdate );
    end loop;
end;
/  

Thomas Kyte
tkyte_at_us.oracle.com
Oracle Government
Bethesda MD  

http://govt.us.oracle.com/ -- downloadable utilities  



Opinions are mine and do not necessarily reflect those of Oracle Corporation  

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 Mon Nov 10 1997 - 00:00:00 CET

Original text of this message