Diificulté avec un trigger de postgres [Résolu]

Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 20 janv. 2014 à 10:42 - Dernière réponse : Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention
- 25 févr. 2015 à 17:53
Bonjour,

je débute les triggers avec postgres et n'arrive pas à le faire fonctionner malgré mes consultations internet.

Voila mon problème:
je dois multiplier 2 données d"une même table et stocker le résultat dans cette même table (colonne existante).

ma 1ére donnée est dans une colonne en numéric ( coefchute)
ma 2iéme est dans une colonne en character varying (surface)
ma troisiéme donnée doit être en numéric et stockée dans resultat

Nom du trigger: coefchutesurface
Nom de ma table : art
nom de ma colonne contenant ma première donnée : surface
nom de ma colonne contenant ma 2ieme donnée :coefchute
nom de ma colonne contenant ma 3ieme donnée : resultat

voila mon code

DECLARE

coefchute CURSOR (art integer) IS SELECT
coefchute
FROM art
WHERE art_int_id = art;

surface CURSOR (art varchar) IS SELECT
surface
FROM art
WHERE art_int_id = art;

resultat CURSOR (art numeric) IS SELECT resultat
FROM art
WHERE art_int_id = art;

BEGIN
-- trigger sur popup

IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') AND (TG_OP = 'INSERT') AND (NEW.art_vch_surface IS NOT NULL)
THEN
NEW.resultat = ((1 - NEW.coefchute) * NEW.surface);


END IF;
RETURN NEW;
END;

J'arrive à l'enregistrer mais ça marche pas, je ne retrouve pas mon résultat dans ma table.

pouvez m'aider, je vais en avoir d'autres à faire avec plusieurs variables...

merci bien
Afficher la suite 

Votre réponse

14 réponses

cs_Robert33 835 Messages postés samedi 15 novembre 2008Date d'inscription 14 janvier 2017 Dernière intervention - 20 janv. 2014 à 18:12
0
Merci
Bonjour

Je ne connais pas bien postgres , mais je ne comprends pas l'utilisation des curseurs

ne te suffit-il pas de mettre un requête d'Update ?
genre (syntaxe SQL serveur)

UPDATE art SET resultat = CONVERT(numeric, surface) * coefchute where art.art_int_id IN (SELECT art_int_id from inserted)
inserted devant correspondre à ta table NEW

par ailleurs ton test
IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') AND (TG_OP = 'INSERT') AND (NEW.art_vch_surface IS NOT NULL)
me semble bizarre
je pense que le "AND (TG_OP = 'INSERT')" est de trop.
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 20 janv. 2014 à 18:44
Merci de ton intervention,
concernant les "cursors .." , je voulais appliquer la méthode de ce lien
http://docs.postgresql.fr/8.0/plpgsql-cursors.html

Je vais avoir une trentaine de triggers plus complexes ( graphiques) à faire ensuite, c'est pour ça que j'aurai voulu utiliser cette méthode.
Si ça marche pas j'y reviendrai plus tard, je débute...
Pour le test, je vais l'enlever et vais le remettre ensuite après l'avoir vérifié.
C'est peut être pas ce qu'il faut faire.

Demain Je vais essayer avec ta requête, cela me parait plus simple et je te tiens au courant, pourras tu me donner un coup de pouce si je me plante ?

Je comprends pas pourquoi tu m'indiques "inserted doit correspondre à ma table New" , tout les opérations se font dans la même table ?

Je vais bosser les triggers en parallèle.
alors si qq maîtrise les triggers, surtout ne pas hésitez à me mettre sur la voie.

merci encore
cs_Robert33 835 Messages postés samedi 15 novembre 2008Date d'inscription 14 janvier 2017 Dernière intervention - 20 janv. 2014 à 19:14
Re...

Dans mon exemple la table "inserted" contient les enregistrements ajoutés ou modifiés, c'est de la terminologie SQL Serveur,
mais en postgress les triggers sont un peu différents car tu dois pouvoir affecter directement la colonne resultat
Soit quelque chose comme
IF NEW.surface IS NOT NULL THEN
NEW.resultat := CAST (NEW.surface as integer) * NEW.coefchute  
END IF
RETURN NEW;
post35 3 Messages postés vendredi 16 août 2013Date d'inscription 4 février 2014 Dernière intervention - 4 févr. 2014 à 12:30
Bonjour,

J'ai "potassé" un trigger avec de l'aide et en suis arrivé à cela qui fonctionne parfaitement bien.

IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
NEW.art_dec_surfaceutile := NEW.art_dec_coefchutearticlepopup * CAST(NEW.art_vch_surface as numeric);
IF (NEW.art_vch_surface IS NOT NULL) THEN
NEW.art_dec_surfaceutile := NEW.art_dec_coefchutearticlepopup * CAST(NEW.art_vch_surface as numeric);

Par contre, je tombe sur une autre difficulté, je vais essayer de m'expliquer :
Lorsque j'envoie mes données de calcul via mon IHM, les calculs de résultats se font et mes données sont correctement updatées dans ma table avec le trigger ci-dessus.
Mais... mon résultat calculé ne reviens pas dans mon IHM si je change mes variables de calculs, je suis obligé de vider le cache pour la donnée updatée de ma table s'affiche dans mon IHM.

j'ai essayé de copier mon résultat après calcul dans un autre champ de la même table en ajoutant cela dans ma fonction trigger, pensant que je contournerai le cache :

BEGIN

IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
NEW.art_dec_surfaceutile := NEW.art_dec_coefchutearticlepopup * CAST(NEW.art_vch_surface as numeric);
IF (NEW.art_vch_surface IS NOT NULL) THEN
NEW.art_dec_surfaceutile := NEW.art_dec_coefchutearticlepopup * CAST(NEW.art_vch_surface as numeric);


------------AJOUT pour copie du resultat dans une autre table-----------
IF (NEW.art_dec_surfaceutilecalcul != NEW.art_dec_surfaceutile) THEN
set art_dec_surfaceutile = art_dec_surfaceutilecalcul;
END IF;
FIN AJOUT ---------------------------------------------------------------------------
END IF;
END IF;
RETURN NEW;
END;

et ça plante.... un problème de chrono ?

je vais essayer ce que me dit yann_lo_san (post ci dessous)
Que faire pour résoudre ce problème, est ce que je suis sur la bonne méthode pour ça ,

Pour info, je bosse avec struts

merci, et simple si possible , je suis toujours débutant ..



Je dois faire une erreur qqpart, ça me plante glassfish ....
Commenter la réponse de cs_Robert33
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 1 févr. 2014 à 18:53
0
Merci
Bonjour,

nul besoin de trigger pour ce genre de cas,
il faut utiliser les "colonnes calculées"

Ce sont des colonnes dans des tables qui se calcules automatiquement selon une expression pouvant contenir d'autre colonnes

ALTER TABLE "art" ADD COLUMN "resultat" REAL

UPDATE "art" SET resultat=((1 - coefchute) * surface)

bye...
post35 3 Messages postés vendredi 16 août 2013Date d'inscription 4 février 2014 Dernière intervention - 4 févr. 2014 à 12:40
bonjour,

Je ne connais pas cette méthode, mais si je comprend, cela me rajoute une colonne dans ma table ?
J'ai déjà une colonne dans la même table pour "héberger" mon résultat.

Vous trouverez mon code de la fonction trigger en commentaire de Robert 33 , qu'en pensez vous ? comment je peux faire ?
merci bien
Commenter la réponse de yann_lo_san
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 4 févr. 2014 à 13:09
0
Merci
Salut,

Si la colonne existe déjà, suffit de faire l'UPDATE

UPDATE "art" SET resultat=((1 - coefchute) * surface)

A partir de la, cette colonne sera calculée automatiquement à chaque INSERT ou UPDATE des données dans cette table.

bye...
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 11 févr. 2014 à 15:37
Merci, mes triggers sont tous Ok, juste une difficulté, comment updater mes résultats dans mon IHM, mes tables étant elles mises à jour?
Voir mon message à Robert, n'oubliez pas que je débute.. donc si je suis pas clair me pardonner svp..
Daniel
Commenter la réponse de yann_lo_san
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 11 févr. 2014 à 15:31
0
Merci
Bonjour,
ç'est Ok, je fais fonctionner mes triggers, j'en ai une dizaine en route sans problème.
Par contre, je voudrais aussi appliquer la requête Update que vous m'aviez indiquée, mais je fais peut être fausse route.
Si je pose cette question , c'est que j'ai un petit problème d'update coté client.
Cette requête me permettrait t'elle de mettre à jour mes données IHM en même temps que ma table ?
Ce qui se passe, enfin il me semble, c'est que mon HTML "charge" de données mes triggers, qui font les calculs, stockent les résultats dans mes tables, mais ceux çi ne s'update pas dans mon IHM ? ( sauf à relancer glassfish ou tout est alors forcément updaté)
Mes tables se mettent pourtant à jour via mes triggers, mais les valeurs qui y sont calculées puis stockées ne réactualisent pas mon IHM.
A mon sens cette requête devrait aller, j'en suis pas sûr, et cela était vrai, je l'implante ou ? pas dans postgres..
merci bien, j'avance en crabe mais j'avance...
daniel
Commenter la réponse de Dbl35
cs_Robert33 835 Messages postés samedi 15 novembre 2008Date d'inscription 14 janvier 2017 Dernière intervention - 14 févr. 2014 à 18:01
0
Merci
Bonsoir

Il est normal que l'IHM ne soit pas mise à jour vu qu'elle ne peut pas savoir ce que les triggers ont modifié.
La seule solution est de refaire une requête pour récupérer les données mises à jour.
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 14 févr. 2014 à 20:16
Bonsoir (Robert ?),

merci pour ton 1er coup de pouce, maintenant les triggers je connais, enfin .. un peu seulement..mais ça me suffit pour l'instant.
Si j'ai bien compris ce que tu viens de me dire, ma requête d'update doit être dans mon jsp ?
Cela ne va pas poser des problèmes de synchronisation, c'est à dire attendre que les triggers aient fini de travailler pour faire l'update en jsp ?

J'ai vu aussi qu'existaient des requêtes dans postgres, quelle est la différence avec les triggers ou les procédures stockées, à priori un trigger est déja une procédure stockée ?

En tout cas, mes triggers.. simples mais impeccables.

merci de ton aide
cs_Robert33 835 Messages postés samedi 15 novembre 2008Date d'inscription 14 janvier 2017 Dernière intervention - 14 févr. 2014 à 20:59
Bonsoir
la différence entre les procédures stockées, les requêtes et les trigger réside principalement dans la forme plus que dans le fond.
Je ne connais pas bien Postgres, mais je ne pense pas que tu ais des problèmes de synchronisation le trigger devrait s'exécuter dès la mise à jour.
Mais dans ton cas, pour être certain, tu devrais essayer l'idée de Yann_lo_san, une colonne avec une expression permet d'être certain du résultat
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 14 févr. 2014 à 22:53
je vais essayer les 2 méthodes, mais je ne sais pas si j'ai compris celle de Yann_lo _san, l'update de ma base ce fait déja en cascade à chaque changement de données par mes triggers, ce qui ne se fait pas c'est l'update de mon IHM.

merci encore, je vois tout ça demain
bonne soirée
Dbl35 72 Messages postés mardi 19 novembre 2013Date d'inscription 11 juillet 2015 Dernière intervention - 25 févr. 2015 à 17:53
Bonjour

Me voila de retour, mes difficultés de l'époque ont été résolues par struts (update IHM en Js >> table postgres).
Maintenant j'ai autre chose comme petit souçi.. que je pensais pourtant pouvoir solutionner facilement, mais je dois faire une erreur je ne sais ou ??

je dois tout simplement copier et mettre à jour une colonne dans une table par rapport à une autre table :

Ma fonction
- Function: test_copie_colonne()
-- DROP FUNCTION test_copie_colonne();

CREATE OR REPLACE FUNCTION test_copie_colonne()
RETURNS trigger AS
$BODY$-- SELECT [DISTINCT ou ALL] * ou liste_de_colonnes FROM nom_des_tables_ou_des_vues

DECLARE
TableOrigine numeric;
TableCopie numeric

BEGIN
SELECT INTO TableCopie colonne_copie() AS NUMERIC;
SELECT INTO TableOrigine colonne_origine () AS NUMERIC;
NEW.colonne_copie := NEW.colonne_origine ;
RETURN NEW;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION test_copie_colonne()
OWNER TO postgres;



Mon trigger
CREATE TRIGGER "TEST_COPIE_COLONNE"
BEFORE INSERT OR UPDATE
ON TableCopie
FOR EACH ROW
EXECUTE PROCEDURE test_copie_colonne();
ALTER TABLE TableCopie DISABLE TRIGGER "TEST_COPIE_COLONNE";


Qu'est ce que je sais pas faire ? pourtant ça me parait si simple et ça marche pas..

Merci bien
Commenter la réponse de cs_Robert33

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.