sql >> Database teknologi >  >> RDS >> Oracle

Oracle DBMS - Læs en tabel før behandling Opdatering i en AFTER trigger - muterende tabel

Bare for at præcisere, er mutationstabel-undtagelsen kastet, fordi du forsøger at læse fra rooms tabel i din funktion, ikke fordi du forsøger at læse fra properties bord. Da du har en trigger på rækkeniveau på rooms , det betyder, at rooms tabel er midt i en ændring, når udløseren på rækkeniveau udløses, og at den muligvis er i en inkonsekvent tilstand. Oracle forhindrer dig i at forespørge i rooms tabel i den situation, fordi resultaterne ikke nødvendigvis er deterministiske eller reproducerbare.

Hvis du har oprettet en udløser på sætningsniveau (ved at fjerne FOR EACH ROW ) og læg din logik der, ville du ikke længere støde på en mutationstabel-undtagelse, fordi rooms tabellen ville ikke længere være i en inkonsekvent tilstand. En udløser på sætningsniveau er dog ikke i stand til at se, hvilke række(r) der blev ændret. Det ville betyde, at du skal kigge på tværs af alle egenskaber for at se, hvilke statusværdier der skal justeres. Det bliver ikke særlig effektivt.

På bekostning af yderligere kompleksitet kan du forbedre ydeevnen ved at registrere, hvilke egenskaber der er ændret i en trigger på rækkeniveau og derefter henvise til det i en udløser på sætningsniveau. Det kræver generelt tre triggere og en pakke, hvilket naturligvis øger antallet af bevægelige brikker væsentligt (hvis du er på 11.2, kan du bruge en sammensat trigger med tre komponent-triggere, som forenkler tingene lidt ved at eliminere behovet for at bruge pakken) . Det ville ligne

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. Tilladelser til at oprette en trigger i mysql

  2. Valg af de sidste 7 dage fra Now() i MYSQL

  3. Sådan repareres en ødelagt SQL-visning

  4. Kan ikke stoppe MySQL på OS X 10.10