PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 11/03/2021 21:48:00

tchazou
Membre

Transaction

Bonsoir à vous,
j'ai besoin de votre assistance au sujet de l'utilisation des transactions dans postgresql
En fait puis je démarrer une transaction dans un trigger ou pas?

Hors ligne

#2 12/03/2021 03:44:53

rjuju
Administrateur

Re : Transaction

Non, et cela serait à priori une mauvaise idée.  C'est le code client qui doit controler les transactions.


Quel problème cherchez-vous à résoudre ?

Hors ligne

#3 12/03/2021 09:16:37

tchazou
Membre

Re : Transaction

Bonjour,
j'ai encore mes idées qui sont confus!
en effet j'ai une table du genre table1(codtab :integer,codel:integer,libeelt: varchar(20)) le champs codel doit être continue, à chaque insertion d'un nouvel enregistrement dans un environnement multiutilisateur, je dois exécuter la requête select (max (codel)+1) pour recupere cette valeur et l'affecter au nouvel enregistrement. le risque de cette méthode est que plusieurs utilisateurs peuvent récupérer la même valeur de codel! Le problème d'intégrité se posera sans doute.

Hors ligne

#4 12/03/2021 09:41:17

rjuju
Administrateur

Re : Transaction

Si vous voulez vous assurer d'avoir une valeur strictement monotone, vous pouvez utiliser une séquence.  Si vous avez en plus réellement besoin de vous assurer de n'avoir aucun trou dans les numéro générés, cela va être beaucoup plus compliqué à gérer, étant donné que vous ne pouvez pas partir du principe que la transaction sera validée au moment où la ligne est générée.

Hors ligne

#5 13/03/2021 00:20:15

dverite
Membre

Re : Transaction

Effectivement la solution en prenant le 1+max(code) n'est sûre que si

- soit la table a été verrouillée avant (forçant la sérialisation). Voir https://docs.postgresql.fr/13/explicit-locking.html

- soit les transactions sont en niveau d'isolation sérialisable (en cas de problème d'insertion concurrente, une erreur spécifique surviendra, à gérer dans le client de manière spécifique en re-soumettant la transaction)


Sinon une solution alternative est, au lieu de calculer 1+max(code), d'avoir une table de générateurs, c'est-à-dire des séquences transactionnées gérées par l'appli, avec un nom et une valeur par compteur.

Une nouvelle valeur est générée avec

UPDATE compteurs SET valeur = valeur+1
WHERE nom_compteur = <paramètre>
RETURNING valeur;

Cette méthode verrouille la ligne en même temps qu'elle produit la nouvelle valeur, ce qui fait qu'elle est sûre par rapport aux exécutions concurrentes.

Hors ligne

#6 17/03/2021 12:45:35

tchazou
Membre

Re : Transaction

Bonjour,
tant que je ne trouve pas une solution à ce problème je n'avancerai vraiment pas. et C'est très utile pour la suite de mon projet:
Toujours la même préoccupation:
Est ce possible de déterminer le nombre d'enregistrement affecté par INSERT/UPDATE/DELETE sans être dans une procédure stockée? si oui un exemple svp

Hors ligne

#7 17/03/2021 14:20:02

dverite
Membre

Re : Transaction

Le nombre d'enregistrements affectés par ces requêtes est renvoyé au client qui a soumis la requête, et les bibliothèques côté client exposent généralement cette information à l'utilisateur.

Par exemple si vous programmez en php il y a https://www.php.net/manual/fr/function. … d-rows.php

Hors ligne

#8 17/03/2021 16:44:18

tchazou
Membre

Re : Transaction

Bonjour et merci pour votre assistance!
Je programme avec WINDEV Version 24 et je ne trouve pas comment faire.....

Hors ligne

#9 18/03/2021 02:17:10

rjuju
Administrateur

Re : Transaction

Si la documentation de windev ne mentionne pas de fonction disponible pour accéder à cette information, j'imagine que ce n'est pas possible.

Hors ligne

#10 06/04/2021 17:18:12

tchazou
Membre

Re : Transaction

Bonsoir à vous chers camarades,
Un soucis qui m'embête sur l'utilisation des triggers.
je voudrais savoir si c'est possible d'annuler l'effet d'une commande INSERT,UPDATE sur une table "Table_emp" lorsque le triggers
"AFTER INSERT/UPDATE" sur chaque ligne de la table "table_emp" ne s'exécute pas correctement.

En d'autre terme je voudrais savoir quel est l'effet d'un TRIGGER "AFTER" appliqué pour chaque ligne lors d'un UPDATE/INSERT. J'ai l'impression que cela n'a aucun effet sur la transaction qui l'a invoquée.

Hors ligne

#11 06/04/2021 17:58:15

rjuju
Administrateur

Re : Transaction

Effectivement, il n'est par définition pas possible d'influer sur une écriture dans un trigger après qu'elle ait eu lieu.  Vous pouvez consulter https://www.postgresql.org/docs/current … ition.html pour plus de détails.

Hors ligne

#12 06/04/2021 19:26:13

tchazou
Membre

Re : Transaction

Je suis perdu!
Dans ce cas que faudra t-il faire? que me conseillez vous de faire pour assurer la cohérence de mes données?

sinon j'aurai un comportement où les données sont insérées dans la table "table1"  sans être insérées dans la table "table2"!! L'insertion dans la table "table2" découle d'un trigger "AFTER INSERT" appliqué sur chaque ligne de la table "table1"...............je n'avance plus...
S.O.S

Hors ligne

#13 06/04/2021 20:05:10

dverite
Membre

Re : Transaction

Voici un conseil: ne faites pas de trigger.

Le trigger est par définition un effet de bord, ce qu'on cherche plutôt à éviter en programmation, et les conceptions basées sur des triggers sont généralement buggées par rapport aux accès concurrents.

La méthode de base consiste à ouvrir une transaction, écrire ce qu'il y a à écrire en faisant autant que de requêtes que nécessaire sur autant de tables que nécessaire, et committer la transaction. Cette méthode marche, les transactions sont faites pour ça.

Si la motivation du trigger est que le code client doit être hyper simple avec idéalement une seule requête, alors mettez toutes les requêtes avec leur logique d'enchaînement  dans des fonctions en plpgsql, et le client se contente d'appeler cette fonction. Ou si vous ne pouvez ou voulez pas créer des fonctions, on peut faire des blocs plpgsql anonymes avec l'instruction DO suivi du code plpgsql.

Hors ligne

#14 20/04/2021 20:18:56

tchazou
Membre

Re : Transaction

Bonsoir chers tous,
j'ai un soucis avec un champs de type timestamp de postgresql 9.6
je suis au Cameroun, il est 19h11min j'ai exécuté la requête suivante "set timezone="Africa/Douala'; afin que le time zone corresponde à celui du Cameroun.

sauf que quand j'insère un enregistrement dans ma base de donnée la date sauvegardée dans le champs de type timestamp est '20h11' soit une heure de plus que l'heure normale!
je ne comprends pas ce qui se passe!
comment corriger définitivement ce type de problème ?
Merci d'avance à vous!

Hors ligne

#15 20/04/2021 21:36:32

gleu
Administrateur

Re : Transaction

Nouvelle question, nouveau thread. Sinon personne ne va s'y retrouver.

En exécutant un "SET timezone=...", vous configurez temporairement la timezone pour cette session. Il faut donc le faire à chaque session, ou le configurer directement dans le fichier postgresql.conf.


Guillaume.

Hors ligne

#16 21/04/2021 04:22:43

rjuju
Administrateur

Re : Transaction

+1 pour un nouveau thread.



Sinon pour compléter la réponse de Guillaume, un champ timestamptz stocke une date de manière à ce qu'elle puisse être affichée vers le timezone voulu, quelquesoit le timezone courant.  Il est donc nécessaire d'effectuer un "SET timezone" si différent de celui par défaut au moment de la lecture.

Hors ligne

#17 04/05/2021 10:26:16

tchazou
Membre

Re : Transaction

Bonjour,
J'ai un problème et j'aimerai avoir une assistance.
j'ai deux tables dans postgresql article(idart,libelle,poidbrut,poidnet,suivistock.......) ayant pour clef unique idart et prixarticle(idart,prixa,prixd,prixg,prixdgros,idagence,.....) ayant pour clef unique "idart,idagence" en effet cette dernière table doit contenir  les prix concernant plusieurs de nos sites distants... on a une table des sites similaire à ceci site(idagence,libelle,localisation,responsable,telephone,boite postale,,...............)
la table "article" contient tous les articles crées et commercialisés. on a bien évidemment des articles qui n'ont pas encore des prix affectés, et par conséquent n'auront aucune référence dans la table "prixarticle"
le problème que j'ai est le suivant: comment afficher tous les enregistrement de la table "article" ayant des correspondances ou pas dans la table "prixarticle"  pour un site particulier par exemple ayant la reference idagence='10'. la requette suivante ne me donne pas le resultant correct: " select * from article  left outer join prixarticle on article.idart=prixarticle.idart where idagence='10' ". seuls les articles du site '10' et ayant une correspondance dans les deux tables sont renvoyés pourtant j'attends plus d'enregistrement. Alors où est l'erreur?

Hors ligne

#18 04/05/2021 10:34:17

dverite
Membre

Re : Transaction

C'est une erreur classique. Le LEFT JOIN prixarticle on article.idart=prixarticle.idart dit qu'on veut  les lignes de prixarticle pour lesquelles la jointure n'est pas satisfaite. Pour ces lignes, le idagence va être NULL. Mais le WHERE idagence='10' dit que le idagence ne peut pas être NULL ce qui élimine les lignes avec idagence à NULL que le LEFT JOIN a ajouté.

Hors ligne

#19 04/05/2021 10:49:02

tchazou
Membre

Re : Transaction

comment faire donc? je veux obtenir en même temps les articles présents dans "article" ayant ou non les correspondances dans prixarticle pour une agence précise.

qu'est ce que cette requête me renverrai?
select * from article  left outer join prixarticle on article.idart=prixarticle.idart  and idagence='10'  en plus quelle difference avec celle-ci: select * from article  left outer join prixarticle on article.idart=prixarticle.idart where idagence='10'

Hors ligne

#20 04/05/2021 12:05:03

dverite
Membre

Re : Transaction

Il y a une 1ere solution qui est d'intégrer idagence à la condition de jointure comme dans la 1ere proposition. Mais il faudrait préfixer idagence par un nom de table car la colonne existe dans les 2 tables.

Une autre solution est de remplacer article par une sous-requête (select * from article where idagence=10) dans la clause FROM. Personnellement je trouve cette solution plus simple à lire.

Hors ligne

Pied de page des forums