sql >> Databasteknik >  >> RDS >> PostgreSQL

Inom en triggerfunktion, hur man får fram vilka fält som uppdateras

Om en "källa" inte "sänder en identifierare" kommer kolumnen att vara oförändrad. Då kan du inte upptäcka om den aktuella UPDATE gjordes av samma källa som den senaste eller av en källa som inte ändrade kolumnen alls. Med andra ord:detta fungerar inte korrekt.

Om "källan" kan identifieras av någon sessionsinformationsfunktion kan du arbeta med den. Gilla:

NEW.column = session_user;

Ovillkorligt för varje uppdatering.

Allmän lösning

Jag hittade ett sätt att lösa det ursprungliga problemet. Kolumnen kommer att ställas in på ett standardvärde i alla uppdatera där kolumnen inte uppdateras (inte i SET lista över UPDATE ).

Nyckelelementet är en utlösare per kolumn introducerad i PostgreSQL 9.0 - en kolumnspecifik utlösare med UPDATE OF column_name klausul.

Utlösaren aktiveras bara om minst en av de listade kolumnerna nämns som mål för UPDATE kommando.

Det är det enda enkla sättet jag hittade för att särskilja om en kolumn uppdaterades med ett nytt värde som är identiskt med det gamla, kontra inte uppdaterat alls.

Man kunde analysera även texten som returneras av current_query() . Men det verkar knepigt och opålitligt.

Triggerfunktioner

Jag antar en kolumn col definierad NOT NULL .

Steg 1: Ställ in col till NULL om oförändrad:

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;

Steg 2: Återgå till gammalt värde. Utlösaren kommer bara att aktiveras om värdet faktiskt uppdaterades (se nedan):

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;

Steg 3: Nu kan vi identifiera den saknade uppdateringen och ställa in ett standardvärde istället:

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;

Triggers

Utlösaren för Steg 2 avfyras per kolumn!

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

Triggernamn är relevanta, eftersom de avfyras i alfabetisk ordning (alla är BEFORE UPDATE )!

Proceduren kan förenklas med något som "per-not-column triggers" eller något annat sätt att kontrollera mållistan för en UPDATE i en trigger. Men jag ser inget handtag för detta.

Om col kan vara NULL , använd alla andra "omöjliga" mellanvärden och kontrollera efter NULL dessutom i triggerfunktion 1:

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

Anpassa resten därefter.



  1. Hur man aktiverar CDC på uppsättning tabeller ELLER aktiverar på alla tabeller i en databas i SQL Server - SQL Server Tutorial

  2. Hur hittar man främmande nyckelberoenden i SQL Server?

  3. Skapa en tabell i SQLite

  4. Hur man ansluter till en MySQL-datakälla i Visual Studio