Se una "fonte" non "invia un identificatore", la colonna rimarrà invariata. Quindi non puoi rilevare se l'attuale UPDATE
è stato eseguito dalla stessa fonte dell'ultima o da una fonte che non ha modificato affatto la colonna. In altre parole:questo non funziona correttamente.
Se la "fonte" è identificabile da qualsiasi funzione di informazioni sulla sessione, puoi lavorare con quella. Come:
NEW.column = session_user;
Incondizionatamente per ogni aggiornamento.
Soluzione generale
Ho trovato un modo per risolvere il problema originale. La colonna verrà impostata su un valore predefinito in qualsiasi aggiorna dove la colonna è non aggiornata (non nel SET
elenco del UPDATE
).
L'elemento chiave è un attivatore per colonna introdotto in PostgreSQL 9.0 - un trigger specifico per la colonna che utilizza UPDATE OF
column_name
clausola.
L'attivatore si attiverà solo se almeno una delle colonne elencate è menzionata come destinazione di UPDATE
comando.
Questo è l'unico modo semplice che ho trovato per distinguere se una colonna è stata aggiornata con un nuovo valore identico al vecchio e se non è stata aggiornata affatto.
Uno potrebbe analizza anche il testo restituito da current_query()
. Ma sembra complicato e inaffidabile.
Funzioni di attivazione
Presumo una colonna col
definito NOT NULL
.
Passaggio 1: Imposta col
a NULL
se invariato:
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;
Passaggio 2: Ripristina il vecchio valore. Il trigger verrà attivato solo se il valore è stato effettivamente aggiornato (vedi sotto):
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;
Passaggio 3: Ora possiamo identificare l'aggiornamento mancante e impostare invece un valore predefinito:
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;
Trigger
Il trigger per il Passaggio 2 viene sparato per colonna!
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();
Nomi trigger sono rilevanti, perché vengono attivati in ordine alfabetico (tutti BEFORE UPDATE
)!
La procedura potrebbe essere semplificata con qualcosa come "attivatori per non colonna" o in qualsiasi altro modo per controllare l'elenco di destinazione di un UPDATE
in un grilletto. Ma non vedo alcuna maniglia per questo.
Se col
può essere NULL
, usa qualsiasi altro valore intermedio "impossibile" e controlla NULL
inoltre nella funzione trigger 1:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
Adatta il resto di conseguenza.