Der Oracle-Mutating-Trigger-Fehler tritt auf, wenn ein Trigger auf die Tabelle verweist, die den Trigger besitzt, was zur Meldung „ORA-04091:Tabellenname mutiert, Trigger/Funktion kann ihn nicht sehen“ führt.
Sehen wir uns die bestehenden Problemumgehungen an.
Der erste, durch das Paket, ist uralt und scheint effektiv zu sein, es dauert jedoch viel Zeit, ihn vorzubereiten und auszuführen. Der zweite ist einfach und wird mit zusammengesetzten Triggern ausgeführt.
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;
Wenn Splinter von einer Ratte zu einem Sensei mutiert, müssen sich die Maler automatisch in Ninja verwandeln. Dieser Trigger scheint geeignet zu sein:
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;
Beim Aktualisieren des Datensatzes jedoch:
update turtles set essence = 'Sensei' where name = 'Splinter'
Der folgende Fehler tritt auf:
ORA-04091:Tabelle SCOTT.TURTLES mutiert, Auslöser/Funktion sieht sie möglicherweise nicht
Löschen wir diesen Trigger:
drop trigger tr_turtles_bue;
Die Methode 1: Verwenden des Pakets und des Triggers auf Anweisungsebene.
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; /
Die Methode 2: Verwenden zusammengesetzter DML-Trigger (verfügbar ab 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;
Versuchen wir Folgendes:
update turtles set essence = 'Sensei' where name = 'Splinter'
Selbst wenn Sie mit einem komplexeren Mutationsfall konfrontiert waren, können Sie die oben erwähnte Idee als Problemumgehung verwenden. Beim Trigger auf Befehlsebene tritt im Gegensatz zum Trigger auf Zeilenebene keine Mutation auf. Sie können entweder Variablen (Tags, Latches, PL-SQL-Tabellen) in einem zusätzlichen Paket verwenden oder Variablen, die für alle Abschnitte des Compound-Triggers global sind, was ab der Version Oracle 11g zu bevorzugen ist. Jetzt kennst du dich also auch mit Kung Fu aus.
Weitere Informationen zu Triggern finden Sie unter:Zusammengesetzte DML-Trigger
Fühlen Sie sich frei, Kommentare hinzuzufügen.