sql >> Databáze >  >> RDS >> Oracle

Oracle DBMS - Přečtěte si tabulku před zpracováním Aktualizace ve spouštěči AFTER - mutující tabulka

Jen pro objasnění, výjimka mutující tabulky je vyvolána, protože se pokoušíte číst z rooms tabulka ve vaší funkci, nikoli proto, že se pokoušíte číst z properties stůl. Protože v rooms máte spouštěč na úrovni řádku , to znamená, že rooms tabulka je uprostřed změny, když se spouští pravidlo na úrovni řádku, a že může být v nekonzistentním stavu. Oracle vám brání v dotazování na rooms v této situaci, protože výsledky nejsou nutně deterministické nebo reprodukovatelné.

Pokud jste vytvořili spouštěč na úrovni příkazu (odstraněním FOR EACH ROW ) a vložte tam svou logiku, již byste nenarazili na výjimku mutující tabulky, protože rooms tabulka by již nebyla v nekonzistentním stavu. Spouštěč na úrovni příkazů však není schopen vidět, které řádky byly změněny. To by znamenalo, že byste se museli podívat na všechny vlastnosti, abyste zjistili, které hodnoty stavu by měly být upraveny. To nebude zvlášť efektivní.

Za cenu další složitosti můžete zlepšit výkon tím, že zachytíte, které vlastnosti se změnily ve spouštěči na úrovni řádku, a poté na ně odkážete ve spouštěči na úrovni příkazu. To obecně vyžaduje tři spouštěče a balíček, což samozřejmě podstatně zvyšuje počet pohybujících se kusů (pokud jste na verzi 11.2, můžete použít složený spouštěč se třemi spouštěcími prvky, což trochu zjednodušuje věci tím, že eliminuje potřebu používat balíček) . Vypadalo by to nějak takto

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. Prohledejte všechny sloupce, všechny tabulky pro konkrétní hodnotu

  2. mysql.connector.errors.InterfaceError:2026 (HY000)

  3. Místní proměnná MySQLdb odkazovaná před přiřazením (jiná než obvykle)

  4. CREATE TABLE MySQL vs T-SQL s příklady syntaxe