sql >> Database teknologi >  >> RDS >> PostgreSQL

Inden for en triggerfunktion, hvordan man får hvilke felter der opdateres

Hvis en "kilde" ikke "sender en identifikator", vil kolonnen være uændret. Så kan du ikke opdage, om den aktuelle UPDATE blev udført af samme kilde som den sidste eller af en kilde, der slet ikke ændrede kolonnen. Med andre ord:dette fungerer ikke korrekt.

Hvis "kilden" kan identificeres af en sessionsinformationsfunktion, kan du arbejde med den. Ligesom:

NEW.column = session_user;

Ubetinget for hver opdatering.

Generel løsning

Jeg fandt en måde at løse det oprindelige problem på. Kolonnen indstilles til en standardværdi i enhver opdatere hvor kolonnen ikke opdateres (ikke i SET liste over UPDATE ).

Nøgleelementet er en udløser pr. kolonne introduceret i PostgreSQL 9.0 - en kolonnespecifik trigger ved hjælp af UPDATE OF column_name klausul.

Udløseren udløses kun, hvis mindst én af de anførte kolonner er nævnt som mål for UPDATE kommando.

Det er den eneste enkle måde, jeg fandt på at skelne mellem, om en kolonne blev opdateret med en ny værdi, der er identisk med den gamle, kontra slet ikke opdateret.

Man kunne parse også teksten returneret af current_query() . Men det virker vanskeligt og upålideligt.

Trigger-funktioner

Jeg antager en kolonne col defineret NOT NULL .

Trin 1: Indstil col til NULL hvis uændret:

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;

Trin 2: Vend tilbage til gammel værdi. Trigger vil kun blive aktiveret, hvis værdien rent faktisk blev opdateret (se nedenfor):

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;

Trin 3: Nu kan vi identificere den manglende opdatering og indstille en standardværdi i stedet:

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;

Udløsere

Udløseren for Trin 2 affyres pr kolonne!

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();

Triggernavne er relevante, fordi de affyres i alfabetisk rækkefølge (alle er BEFORE UPDATE )!

Proceduren kunne forenkles med noget som "per-not-column triggers" eller en anden måde at kontrollere mållisten for en UPDATE på i en udløser. Men jeg kan ikke se noget håndtag for dette.

Hvis col kan være NULL , brug enhver anden "umulig" mellemværdi og tjek for NULL desuden i triggerfunktion 1:

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

Tilpas resten i overensstemmelse hermed.



  1. Hvad og hvornår skal jeg angive setFetchSize()?

  2. Streng til dato i Oracle med millisekunder

  3. SQL CASE-erklæring

  4. Planetarisk justering