Diificulté avec un trigger de postgres

Résolu
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 - 20 janv. 2014 à 10:42
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 - 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
A voir également:

5 réponses

cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
20 janv. 2014 à 18:12
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.
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
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
0
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
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;
0
post35 Messages postés 3 Date d'inscription vendredi 16 août 2013 Statut Membre Dernière intervention 4 février 2014
Modifié par post35 le 4/02/2014 à 12:36
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 ....
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
1 févr. 2014 à 18:53
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...
0
post35 Messages postés 3 Date d'inscription vendredi 16 août 2013 Statut Membre Dernière intervention 4 février 2014
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
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
4 févr. 2014 à 13:09
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...
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
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
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
11 févr. 2014 à 15:31
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
14 févr. 2014 à 18:01
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.
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
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
0
cs_Robert33 Messages postés 834 Date d'inscription samedi 15 novembre 2008 Statut Membre Dernière intervention 14 janvier 2017 33
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
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
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
0
Dbl35 Messages postés 71 Date d'inscription mardi 19 novembre 2013 Statut Membre Dernière intervention 11 juillet 2015 1
Modifié par Dbl35 le 25/02/2015 à 17:55
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
0
Rejoignez-nous