Oracle-mutationstriggerfejlen opstår, når en trigger refererer til den tabel, der ejer triggeren, hvilket resulterer i meddelelsen "ORA-04091:tabelnavnet muterer, triggeren/funktionen ser den muligvis ikke".
Lad os se på de eksisterende løsninger.
Den første, gennem pakken, er gammel og ser ud til at være effektiv, men det tager meget tid at forberede og køre den. Den anden er enkel og udføres ved hjælp af sammensatte triggere.
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 muterer fra en rotte til en sensei, bliver malerne automatisk nødt til at blive til ninjaer. Denne trigger ser ud til at være egnet:
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 opdaterer posten:
update turtles set essence = 'Sensei' where name = 'Splinter'
Følgende fejl opstår:
ORA-04091:tabel SCOTT.TURTLES muterer, trigger/funktion kan muligvis ikke se den
Lad os slette denne trigger:
drop trigger tr_turtles_bue;
Metode 1: Brug af pakken og udløseren på instruktionsniveau.
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;
/ Metode 2: Brug af sammensatte DML-triggere (tilgængelig fra 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; Lad os prøve følgende:
update turtles set essence = 'Sensei' where name = 'Splinter'

Selvom du stod over for et mere komplekst tilfælde af mutation, kan du bruge ovennævnte idé som en løsning. I instruktions-niveau-triggeren, i modsætning til række-niveau-triggeren, sker der ingen mutation. Du kan bruge enten variabler (tags, latches, PL SQL-tabeller) i en ekstra pakke eller variabler, der er globale for alle sektioner af den sammensatte trigger, hvilket er at foretrække at starte med versionen Oracle 11g. Så nu kender du også kung fu.
Du kan finde yderligere oplysninger om udløsere på:Sammensatte DML-udløsere
Du er velkommen til at tilføje eventuelle kommentarer.