Question

J'ai une fonction de déclenchement pour un test de table qui a le code suivant:

IF TG_OP='UPDATE' THEN
    IF OLD.locked > 0 AND
 (       OLD.org_id <> NEW.org_id OR
            OLD.document_code <> NEW.document_code OR
            -- other columns ...
 )
THEN
    RAISE EXCEPTION 'Message';
-- more code

Je vérifie statiquement toute nouvelle valeur de la colonne avec sa valeur précédente pour assurer l'intégrité. Maintenant, chaque fois que mes changements de logique métier et je dois ajouter de nouvelles colonnes dans cette table, je vais devoir modifier ce déclencheur chaque fois. Je pensais que ce serait mieux si je pouvais en quelque sorte dynamiquement vérifier toutes les colonnes de cette table, sans taper explicitement leur nom.

Comment peut-il être fait?

Était-ce utile?

La solution

Jetez un oeil à la information_schema, il y a une vue « colonnes ». Exécuter une requête pour obtenir tous les columnNames actuels de la table qui a tiré sur la gâchette:

SELECT 
    column_name 
FROM 
    information_schema.columns 
WHERE 
    table_schema = TG_TABLE_SCHEMA 
AND 
    table_name = TG_TABLE_NAME;

Boucle par le résultat et là vous allez!

Plus d'informations peuvent être trouvées dans le fin manuel.

Autres conseils

A partir de la documentation 9.0 beta2 au sujet de la clause de WHEN dans les déclencheurs, ce qui pourrait être en mesure d'être utilisé dans les versions antérieures dans le corps de déclenchement:

OLD.* IS DISTINCT FROM NEW.*

ou peut-être ( de notes de version 8.2 )

IF row(new.*) IS DISTINCT FROM row(old.*)

Utilisez pl / perl ou pl / python. Ils sont beaucoup mieux adaptés à ces tâches. beaucoup mieux.

Vous pouvez également installer hstore nouvelle , et de l'utiliser de ligne-> hstore sémantique , mais c'est certainement pas une bonne idée lors de l'utilisation normale des types de données.

Dans Postgres 9.0 ou version ultérieure ajouter un clause WHEN votre définition de déclenchement (déclaration de CREATE TRIGGER):

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD IS DISTINCT FROM NEW)  -- parentheses required!
EXECUTE PROCEDURE ...;

Uniquement possible pour les déclencheurs BEFORE / AFTER UPDATE , où sont définies à la fois OLD et NEW. Vous obtiendrez une exception en essayant d'utiliser cette clause WHEN avec des déclencheurs de INSERT ou DELETE.

Et simplifier radicalement la détente fonction en conséquence:

...
IF OLD.locked > 0 THEN
   RAISE EXCEPTION 'Message';
END IF;
...

Pas besoin de IF TG_OP='UPDATE' ... test car ce déclencheur ne fonctionne que pour UPDATE de toute façon.

Ou déplacer cette condition dans la clause WHEN aussi:

CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD.locked > 0
  AND OLD IS DISTINCT FROM NEW)
EXECUTE PROCEDURE ...;

ne laissant qu'une RAISE EXCEPTION inconditionnelle dans votre fonction de déclenchement, qui est appelé uniquement en cas de besoin pour commencer.

Lisez les petits caractères:

  

Dans un déclencheur BEFORE, la condition de WHEN est évaluée juste avant la   fonction est ou serait exécuté, donc l'utilisation WHEN est pas matériellement   différent de tester le même état au début de la   fonction déclencheur. Note en particulier que la ligne de NEW vu par la   condition est la valeur actuelle, comme précédemment éventuellement modifié par   déclencheurs. En outre, un état de BEFORE de déclenchement WHEN ne peut pas   examiner les colonnes du système de la rangée de NEW (comme oid), car celles   n'aura pas encore été fixée.

     

Dans un déclencheur AFTER, la condition de WHEN est évaluée juste après la   mise à jour de ligne se produit, et il détermine si un événement est mis en attente à   feu sur la gâchette à la fin de l'instruction. Alors, quand un de déclencheur de AFTER   condition WHEN ne retourne pas vrai, il ne faut pas faire la queue d'un   événement, ni pour récupérer à la ligne à la fin de la déclaration. Cela peut entraîner   speedups importantes dans les déclarations qui modifient de lignes, si le   déclencheur ne doit être tiré pour quelques lignes.

Related:

Pour répondre aussi le titre de la question

  

Est-il possible de boucle de manière dynamique à travers les colonnes d'une table?

Oui. Exemples:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top