sql >> Databasteknik >  >> RDS >> Oracle

Oracle DBMS - Läs en tabell innan bearbetning Uppdatering i en AFTER trigger - muterande tabell

Bara för att förtydliga, mutationstabellundantaget kastas eftersom du försöker läsa från rooms tabell i din funktion, inte för att du försöker läsa från properties tabell. Eftersom du har en utlösare på radnivå på rooms , det betyder att rooms tabellen är mitt i en förändring när utlösaren på radnivå aktiveras och att den kan vara i ett inkonsekvent tillstånd. Oracle hindrar dig från att fråga rooms tabell i den situationen eftersom resultaten inte nödvändigtvis är deterministiska eller reproducerbara.

Om du skapade en utlösare på satsnivå (att ta bort FOR EACH ROW ) och lägg din logik där, skulle du inte längre stöta på ett mutationstabellundantag eftersom rooms tabellen inte längre skulle vara i ett inkonsekvent tillstånd. En utlösare på satsnivå kan dock inte se vilken eller vilka rader som har ändrats. Det skulle innebära att du måste titta över alla egenskaper för att se vilka statusvärden som bör justeras. Det kommer inte att vara särskilt effektivt.

Till priset av ytterligare komplexitet kan du förbättra prestandan genom att fånga vilka egenskaper som ändrats i en utlösare på radnivå och sedan hänvisa till det i en utlösare på uttalandenivå. Det kräver i allmänhet tre triggers och ett paket, vilket uppenbarligen ökar antalet rörliga bitar avsevärt (om du är på 11.2 kan du använda en sammansatt trigger med tre komponentutlösare som förenklar saker och ting lite genom att eliminera behovet av att använda paketet) . Det skulle se ut ungefär som

CREATE OR REPLACE PACKAGE trigger_collections
AS
  TYPE modified_property_tbl IS TABLE OF properties.property_id%type;
  g_modified_properties modified_property_tbl;
END;

-- Initialize the collection in a before statement trigger just in case
-- there were values there from a prior run
CREATE OR REPLACE TRIGGER trg_initialize_mod_prop_coll
  BEFORE INSERT OR UPDATE ON rooms
BEGIN
  trigger_collections.g_modified_properties := trigger_collections.modified_property_tbl();
END;

-- Put the property_id of the modified row in the collection
CREATE OR REPLACE TRIGGER trg_populate_mod_prop_coll
  AFTER INSERT OR UPDATE ON rooms
  FOR EACH ROW
BEGIN
  trigger_collections.g_modified_properties.extend();
  trigger_collections.g_modified_properties( trigger_collections.g_modified_properties.count + 1 ) := :new.property_id;
END;

CREATE OR REPLACE TRIGGER trg_process_mod_prop_coll
  AFTER INSERT OR UPDATE ON rooms
BEGIN
  FOR p IN 1 .. trigger_collections.g_modified_properties.count
  LOOP
    IF prop_vacancy_query( trigger_collections.g_modified_properties(i) ) = 0 
    THEN
      ...
END;



  1. lagrad procedur för att välja alla rader från tabellen i Oracle

  2. Beräkna skillnaden mellan min och max för varje kolumn endast om den är högre än 0

  3. Python 'float64' kan inte konverteras till en MySQL-typ men i manuell fråga är det inga problem

  4. SQL-syntaxfel - Haversine-formel