De Oracle-muterende triggerfout treedt op wanneer een trigger verwijst naar de tabel die eigenaar is van de trigger, wat resulteert in het bericht "ORA-04091:tabelnaam muteert, trigger/functie ziet het mogelijk niet".
Laten we eens kijken naar de bestaande tijdelijke oplossingen.
De eerste, via het pakket, is oud en lijkt effectief te zijn, maar het kost veel tijd om het voor te bereiden en uit te voeren. De tweede is eenvoudig en wordt uitgevoerd met samengestelde 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;
Wanneer Splinter muteert van een rat in een sensei, zullen de schilders automatisch in ninja's moeten veranderen. Deze trigger lijkt geschikt:
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;
Bij het bijwerken van het record:
update turtles set essence = 'Sensei' where name = 'Splinter'
De volgende fout treedt op:
ORA-04091:tabel SCOTT.TURTLES muteert, trigger/functie ziet het mogelijk niet
Laten we deze trigger verwijderen:
drop trigger tr_turtles_bue;
De methode 1: Het pakket en de trigger op instructieniveau gebruiken.
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; /
De methode 2: Samengestelde DML-triggers gebruiken (beschikbaar vanaf 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;
Laten we het volgende proberen:
update turtles set essence = 'Sensei' where name = 'Splinter'
Zelfs als u te maken krijgt met een complexer geval van mutatie, kunt u het bovengenoemde idee als een tijdelijke oplossing gebruiken. In de trigger op instructieniveau vindt, in tegenstelling tot de trigger op rijniveau, geen mutatie plaats. U kunt variabelen (tags, vergrendelingen, PL SQL-tabellen) in een extra pakket gebruiken, of variabelen die globaal zijn voor alle secties van de samengestelde trigger, wat bij voorkeur begint met de versie Oracle 11g. Dus nu ken je ook kungfu.
U kunt aanvullende informatie over triggers vinden op:Samengestelde DML-triggers
Voel je vrij om opmerkingen toe te voegen.