sql >> Database >  >> RDS >> Oracle

Oracle als tijdelijke oplossing voor het muteren van tabellen

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.


  1. SQL (ORACLE):ORDER BY en LIMIT

  2. Vul een tekenreeks in met voorloopnullen zodat deze 3 tekens lang is in SQL Server 2008

  3. Een andere manier om automatische updates van statistieken te bekijken

  4. SQL-ontwikkelaar 4