sql >> Databáze >  >> RDS >> PostgreSQL

Nekonečná smyčka ve funkci spouštění

ELSE větev lze radikálně zjednodušit. Ale pár dalších věcí je neefektivních / nepřesných / nebezpečných:

CREATE OR REPLACE FUNCTION sample_trigger_func()
  RETURNS TRIGGER AS
$func$
BEGIN
   IF TG_OP = 'DELETE' THEN
      RAISE INFO 'OLD: %', OLD.name;

      EXECUTE format('INSERT INTO %I SELECT ($1).*', TG_TABLE_NAME || '_deletes')
      USING OLD #= hstore('{mod_op, mod_datetime}'::text[]
                         , ARRAY[left(TG_OP, 1), now()::text]);
      RETURN OLD;
   ELSE  -- insert, update
      NEW.mod_op       := left(TG_OP, 1);
      NEW.mod_datetime := now();

      RETURN NEW;
   END IF;
END
$func$  LANGUAGE plpgsql;
  • V ELSE větev stačí přiřadit k NEW přímo. Není třeba dynamičtějšího SQL - což by znovu spustilo stejný spouštěč a způsobilo by nekonečnou smyčku. To je hlavní chyba.

  • VRÁTIT NOVÝ; mimo IF konstrukt by přerušil vaši spouštěcí funkci pro DELETE , protože NOVINKA není přiřazeno pro DELETE.

  • Klíčovou funkcí je použití hstore a operátor hstore #= pro dynamickou změnu dvou vybraných polí dobře známého typu řádku - to je neznámé v době psaní kódu. Tímto způsobem nezasahujete do původního STARÉHO hodnotu, což může mít překvapivý vedlejší účinek, pokud máte v řetězci událostí více spouštěčů.

    OLD #= hstore('{mod_op, mod_datetime}'::text[]
                 , ARRAY[left(TG_OP, 1), now()::text]);
    

    Doplňkový modul hstore musí být nainstalován. Podrobnosti:

    Pomocí hstore(text[], text[]) zde vytvoříte hstore hodnotu s více poli za běhu.

  • Operátor přiřazení v plpgsql je := :

  • Všimněte si, že jsem použil název sloupce mod_datetime místo zavádějícího mod_date , protože sloupec je zjevně časové razítko a nikoli datum .

Během toho jsem přidal několik dalších vylepšení. A samotná spoušť by měla vypadat takto:

CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();

SQL Fiddle.




  1. Volání uložených procedur z Javy

  2. ORACLE SQL:Doplňte chybějící data

  3. MySQL, dvě tabulky zobrazující informace z obou tabulek

  4. Spustit spouštěč pouze při aktualizaci určitých sloupců (SQL Server)