Si une "source" n'"envoie pas d'identifiant", la colonne sera inchangée. Ensuite, vous ne pouvez pas détecter si la UPDATE
actuelle a été fait par la même source que la dernière ou par une source qui n'a pas du tout changé la colonne. En d'autres termes :cela ne fonctionne pas correctement.
Si la "source" est identifiable par n'importe quelle fonction d'information de session, vous pouvez travailler avec cela. Comme :
NEW.column = session_user;
Inconditionnellement pour chaque mise à jour.
Solution générale
J'ai trouvé un moyen de résoudre le problème d'origine. La colonne sera définie sur une valeur par défaut dans tout mettre à jour où la colonne n'est pas mise à jour (pas dans le SET
liste des UPDATE
).
L'élément clé est un déclencheur par colonne introduit dans PostgreSQL 9.0 - un déclencheur spécifique à une colonne utilisant le UPDATE OF
column_name
clause.
Le déclencheur ne se déclenchera que si au moins une des colonnes répertoriées est mentionnée comme cible de la
UPDATE
commande.
C'est le seul moyen simple que j'ai trouvé pour distinguer si une colonne a été mise à jour avec une nouvelle valeur identique à l'ancienne, ou pas du tout mise à jour.
On pourrait analyse également le texte renvoyé par current_query()
. Mais cela semble délicat et peu fiable.
Fonctions de déclenchement
Je suppose une colonne col
défini NOT NULL
.
Étape 1 : Définir col
à NULL
si inchangé :
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;
Étape 2 : Revenir à l'ancienne valeur. Le déclencheur ne sera activé que si la valeur a été réellement mise à jour (voir ci-dessous) :
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;
Étape 3 : Nous pouvons maintenant identifier la mise à jour manquante et définir une valeur par défaut à la place :
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;
Déclencheurs
Le déclencheur de l'Étape 2 est déclenché par colonne !
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();
Noms des déclencheurs sont pertinents, car ils sont déclenchés par ordre alphabétique (tous étant BEFORE UPDATE
) !
La procédure pourrait être simplifiée avec quelque chose comme des "déclencheurs par colonne" ou tout autre moyen de vérifier la liste cible d'un UPDATE
dans un déclencheur. Mais je ne vois pas de poignée pour cela.
Si col
peut être NULL
, utilisez toute autre valeur intermédiaire "impossible" et vérifiez NULL
en plus dans la fonction de déclenchement 1 :
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
Adaptez le reste en conséquence.