sql >> Database >  >> RDS >> PostgreSQL

Binnen een triggerfunctie, hoe u kunt zien welke velden worden bijgewerkt?

Als een "bron" geen "identificatiecode verzendt", blijft de kolom ongewijzigd. Dan kunt u niet detecteren of de huidige UPDATE is gedaan door dezelfde bron als de vorige of door een bron die de kolom helemaal niet heeft gewijzigd. Met andere woorden:dit werkt niet goed.

Als de "bron" identificeerbaar is door een sessie-informatiefunctie, kunt u daarmee werken. Vind ik leuk:

NEW.column = session_user;

Onvoorwaardelijk voor elke update.

Algemene oplossing

Ik heb een manier gevonden om het oorspronkelijke probleem op te lossen. De kolom wordt ingesteld op een standaardwaarde in elke update waar de kolom is niet bijgewerkt (niet in de SET lijst van de UPDATE ).

Het belangrijkste element is een trigger per kolom geïntroduceerd in PostgreSQL 9.0 - een kolomspecifieke trigger met behulp van de UPDATE OF column_name clausule.

De trigger wordt alleen geactiveerd als ten minste één van de vermelde kolommen wordt vermeld als een doelwit van de UPDATE commando.

Dat is de enige eenvoudige manier die ik heb gevonden om te onderscheiden of een kolom is bijgewerkt met een nieuwe waarde die identiek is aan de oude, of helemaal niet is bijgewerkt.

Een zou ontleden ook de tekst die wordt geretourneerd door current_query() . Maar dat lijkt lastig en onbetrouwbaar.

Triggerfuncties

Ik neem aan dat een kolom col gedefinieerd NOT NULL .

Stap 1: Stel col in naar NULL indien ongewijzigd:

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;

Stap 2: Terug naar oude waarde. Trigger wordt alleen geactiveerd als de waarde daadwerkelijk is bijgewerkt (zie hieronder):

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;

Stap 3: Nu kunnen we de ontbrekende update identificeren en in plaats daarvan een standaardwaarde instellen:

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

De trigger voor Stap 2 wordt per kolom afgevuurd!

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

Triggernamen zijn relevant, omdat ze in alfabetische volgorde worden geactiveerd (allemaal BEFORE UPDATE )!

De procedure kan worden vereenvoudigd met iets als "triggers per niet-kolom" of een andere manier om de doellijst van een UPDATE te controleren in een trekker. Maar ik zie hier geen handvat voor.

Als col kan NULL zijn , gebruik een andere "onmogelijke" tussenwaarde en controleer op NULL bovendien in triggerfunctie 1:

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

Pas de rest dienovereenkomstig aan.



  1. Spotlight Cloud gebruiken om blokkering van SQL Server op te lossen

  2. nvarchar(max) vs NText

  3. SQL Server Agent-waarschuwingen

  4. Hoe de Ln()-functie werkt in PostgreSQL