Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Oracle jako obejście tabel mutacji

Błąd mutującego wyzwalacza Oracle występuje, gdy wyzwalacz odwołuje się do tabeli, do której należy wyzwalacz, co powoduje wyświetlenie komunikatu „ORA-04091:nazwa tabeli mutuje, wyzwalacz/funkcja może jej nie widzieć”.

Rzućmy okiem na istniejące obejścia.

Pierwsza, poprzez pakiet, jest stara i wydaje się skuteczna, jednak jej przygotowanie i uruchomienie zajmuje dużo czasu. Drugi jest prosty i wykonywany przy użyciu wyzwalaczy złożonych.

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;

Kiedy Splinter zmutuje ze szczura w senseia, malarze będą musieli automatycznie zmienić się w ninja. Ten wyzwalacz wydaje się odpowiedni:

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;

Jednak podczas aktualizowania rekordu:

update turtles
   set essence = 'Sensei'
 where name = 'Splinter'

Wystąpił następujący błąd:

ORA-04091:tabela SCOTT.TURTLES mutuje, wyzwalacz/funkcja może jej nie widzieć

Usuńmy ten wyzwalacz:

drop trigger tr_turtles_bue;

Metoda 1: Korzystanie z pakietu i wyzwalacza na poziomie instrukcji.

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;
/

Metoda 2: Korzystanie ze złożonych wyzwalaczy DML (dostępne od 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;

Spróbujmy wykonać następujące czynności:

update turtles
   set essence = 'Sensei'
 where name = 'Splinter'

Nawet jeśli miałeś do czynienia z bardziej złożonym przypadkiem mutacji, możesz użyć powyższego pomysłu jako obejście. W wyzwalaczu na poziomie instrukcji, w przeciwieństwie do wyzwalacza na poziomie wiersza, nie występuje żadna mutacja. Możesz używać zmiennych (tagi, latchy, tabele PL SQL) w dodatkowym pakiecie lub zmiennych globalnych dla wszystkich sekcji wyzwalacza złożonego, co jest preferowane począwszy od wersji Oracle 11g. Więc teraz znasz również kung fu.

Dodatkowe informacje na temat wyzwalaczy można znaleźć pod adresem:Złożone wyzwalacze DML

Zapraszam do dodawania komentarzy.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Narzędzia do generowania diagramu bazy danych/diagramu ER z istniejącej bazy danych Oracle?

  2. ADD_MONTHS() Funkcja w Oracle

  3. System.Data.OracleClient wymaga oprogramowania klienckiego Oracle w wersji 8.1.7 lub nowszej

  4. Dlaczego nieprawidłowa konwersja zażądała KODU BŁĘDU:17132?

  5. Czy można skorzystać ze zwrotu w procedurze składowanej?