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.