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.