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.