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

Jak v rámci spouštěcí funkce získat, která pole se aktualizují

Pokud „zdroj“ neposílá identifikátor, sloupec se nezmění. Pak nemůžete zjistit, zda je aktuální UPDATE bylo provedeno stejným zdrojem jako poslední nebo zdrojem, který sloupec vůbec nezměnil. Jinými slovy:toto nefunguje správně.

Pokud je „zdroj“ identifikovatelný pomocí jakékoli funkce informací o relaci, můžete s tím pracovat. Jako:

NEW.column = session_user;

Bezpodmínečně pro každou aktualizaci.

Obecné řešení

Našel jsem způsob, jak vyřešit původní problém. Sloupec bude nastaven na výchozí hodnotu libovolné aktualizovat, kde sloupec není aktualizován (nikoli v SET seznam UPDATE ).

Klíčovým prvkem je spouštěč pro každý sloupec představen v PostgreSQL 9.0 – spouštěč specifický pro sloupec pomocí UPDATE OF column_name doložka.

Spouštěč se spustí, pouze pokud je alespoň jeden z uvedených sloupců uveden jako cíl UPDATE příkaz.

To je jediný jednoduchý způsob, jak jsem našel, jak rozlišit, zda byl sloupec aktualizován novou hodnotou shodnou se starou, nebo zda nebyl aktualizován vůbec.

Jeden mohl také analyzovat text vrácený current_query() . Ale to se zdá být složité a nespolehlivé.

Spouštěcí funkce

Předpokládám sloupec col definováno NOT NULL .

Krok 1: Nastavte col na NULL pokud se nezmění:

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
  RETURNS trigger AS
$func$
BEGIN
   IF OLD.col = NEW.col THEN
      NEW.col := NULL;      -- "impossible" value
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Krok 2: Vrátit se na starou hodnotu. Spouštěč se spustí pouze v případě, že byla hodnota skutečně aktualizována (viz níže):

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
  RETURNS trigger AS
$func$
BEGIN
   IF NEW.col IS NULL THEN
      NEW.col := OLD.col;
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Krok 3: Nyní můžeme identifikovat chybějící aktualizaci a místo toho nastavit výchozí hodnotu:

CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
  RETURNS trigger AS
$func$
BEGIN
   IF NEW.col IS NULL THEN
      NEW.col := 'default value';
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

Spouštěče

Spouštěč pro Krok 2 se spouští za sloupec!

CREATE TRIGGER upbef_step1
  BEFORE UPDATE ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step1();

CREATE TRIGGER upbef_step2
  BEFORE UPDATE OF col ON tbl                -- key element!
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step2();

CREATE TRIGGER upbef_step3
  BEFORE UPDATE ON tbl
  FOR EACH ROW
  EXECUTE PROCEDURE trg_tbl_upbef_step3();

Názvy spouštěčů jsou relevantní, protože jsou spouštěny v abecedním pořadí (vše BEFORE UPDATE )!

Postup by mohl být zjednodušen pomocí něčeho jako "spouštěče pro jednotlivé sloupce" nebo jakýmkoli jiným způsobem, jak zkontrolovat seznam cílů UPDATE ve spoušti. Ale nevidím pro to žádné řešení.

Pokud col může být NULL , použijte jakoukoli jinou "nemožnou" mezihodnotu a zkontrolujte NULL navíc ve funkci spouštění 1:

IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
    NEW.col := '#impossible_value#';
END IF;

Zbytek tomu přizpůsobte.



  1. SQL – volání uložené procedury pro každý záznam

  2. Ukládání souborů do SQL databáze pomocí FILESTREAM – část 1

  3. Jak získat kumulativní celkový počet uživatelů za den v MySQL

  4. Jak replikovat pouze INSERTy, nikoli DELETE/UPDATE na Slony Slave Node?