Oracles muterande triggerfel uppstår när en trigger refererar till tabellen som äger triggern, vilket resulterar i meddelandet "ORA-04091:tabellnamnet muterar, triggern/funktionen kanske inte ser det".
Låt oss ta en titt på de befintliga lösningarna.
Den första, genom paketet, är gammal och verkar vara effektiv, men det tar mycket tid att förbereda och köra den. Den andra är enkel och utförs med hjälp av sammansatta triggers.
create table turtles as select 'Splinter' name, 'Rat' essence from dual union all select 'Leonardo', 'Painter' from dual union all select 'Rafael', 'Painter' from dual union all select 'Michelangelo', 'Painter' from dual union all select 'Donatello', 'Painter' from dual;
När Splinter muterar från en råtta till en sensei måste målarna automatiskt förvandlas till ninja. Denna utlösare verkar vara lämplig:
create or replace trigger tr_turtles_bue before update of essence on turtles for each row when ( new.name = 'Splinter' and old.essence = 'Rat' and new.essence = 'Sensei' ) begin update turtles set essence = 'Ninja' where essence = 'Painter'; end;
Men när du uppdaterar posten:
update turtles set essence = 'Sensei' where name = 'Splinter'
Följande fel uppstår:
ORA-04091:Tabell SCOTT.TURTLES muterar, trigger/funktion kanske inte ser den
Låt oss ta bort denna utlösare:
drop trigger tr_turtles_bue;
Metoden 1: Använda paketet och utlösaren på instruktionsnivå.
create or replace package pkg_around_mutation is bUpdPainters boolean; procedure update_painters; end pkg_around_mutation; / create or replace package body pkg_around_mutation is procedure update_painters is begin if bUpdPainters then bUpdPainters := false; update turtles set essence = 'Ninja' where essence = 'Painter'; end if; end; end pkg_around_mutation; / create or replace trigger tr_turtles_bue before update of essence on turtles for each row when ( new.name = 'Splinter' and old.essence = 'Rat' and new.essence = 'Sensei' ) begin pkg_around_mutation.bUpdPainters := true; end tr_turtles_bue; / create or replace trigger tr_turtles_bu after update on turtles begin pkg_around_mutation.update_painters; end tr_turtles_bu; /
Metoden 2: Använder sammansatta DML-utlösare (tillgänglig från och med Oracle 11g).
create or replace trigger tr_turtles_ue for update of essence on turtles compound trigger bUpdPainters boolean; before each row is begin if :new.name = 'Splinter' and :old.essence = 'Rat' and :new.essence = 'Sensei' then bUpdPainters := true; end if; end before each row; after statement is begin if bUpdPainters then update Turtles set essence = 'Ninja' where essence = 'Painter'; end if; end after statement; end tr_turtles_ue;
Låt oss prova följande:
update turtles set essence = 'Sensei' where name = 'Splinter'
Även om du stod inför ett mer komplext fall av mutation, kan du använda den ovan nämnda idén som en lösning. I utlösaren på instruktionsnivån, till skillnad från utlösaren på radnivån, sker ingen mutation. Du kan använda antingen variabler (taggar, låsningar, PL SQL-tabeller) i ett extra paket eller variabler som är globala för alla sektioner av den sammansatta utlösaren, vilket är att föredra från och med versionen Oracle 11g. Så nu vet du också kung fu.
Du kan hitta ytterligare information om triggers på:Compound DML Triggers
Lägg gärna till kommentarer.