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 23/06/2010 18:06:41

LeHibou
Membre

Trigger qui récupère les valeurs induites

Bonjour à tous,

J'en vois déjà certains grogner de mon retour.

Tout d'abord, voilà où j'en suis:
BDD 20 tables, impressions pour factures gérées avec Calc.

Mais il y a encore une dernière chose qui me dérange.
Est-il possible à mon trigger de renvoyer le résultat de la requête que j'ai écrite dans une colonne bien précise?

Je viens de rééditer le message pour la seconde fois. j'ai supprimé les tables qui ne servaient pas à la compréhension du problème.

Dans mon  trigger, si je supprime la requête et remplace "Id_Matière" dans "Values ("Id_Matiere"..."par un Id existant, alors ça marche. mais je veux qu'il fasse une requête.
La requête, une fois faite, me donne les informations dont j'ai besoin.

ce que j'aimerais, c'est que mon trigger insère dans stocks."Matiere"."Id_Matiere" le résultat de la requête qu'il contient (select... from...)
Lui même est situé dans Facturation. Donc un autre schéma. Ce trigger envoie donc à une table étrangère les valeurs de la table locale ET le résultat d'une requête qui se fait sur une table voisine.


J'ai créé le trigger suivant:

CREATE OR REPLACE FUNCTION "Facturation"."MAJ_Quantite_Matiere"()
  RETURNS trigger AS
$BODY$Begin
SELECT 
"Id_Matiere"
FROM 
  "Facturation"."Nom_Prod_Fini"
WHERE 
  "Nom_Prod_Fini"."Nom_Produit" = "Nom_Produit";

	If (TG_OP = 'INSERT')
		Then Insert into stocks."Matiere" ("Id_Matière","Quantite_commande_(kg)","Quantite_casse_(kg)","Quantite_Sortie_(kg)")
		Values ("Id_Matiere", 0,0,-(new."Quantite"));
		Return new;

	end if;
	return new;

	
End;$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
ALTER FUNCTION "Facturation"."MAJ_Quantite_Matiere"() OWNER TO postgres;

Ce n'est pas simple à expliquer.
Mais je serais ravi de m'exprimer à nouveau sur les points qu'il faudra.

Merci

Dernière modification par LeHibou (23/06/2010 18:33:53)

Hors ligne

#2 23/06/2010 18:46:05

gleu
Administrateur

Re : Trigger qui récupère les valeurs induites

Il est possible que vous cherchiez à faire ça:

CREATE OR REPLACE FUNCTION "Facturation"."MAJ_Quantite_Matiere"()
  RETURNS trigger AS
$BODY$
DECLARE
  id text;
BEGIN
  SELECT INTO id "Id_Matiere"
  FROM "Facturation"."Nom_Prod_Fini"
  WHERE "Nom_Prod_Fini"."Nom_Produit" = "Nom_Produit";

  IF TG_OP = 'INSERT'
  THEN
    INSERT INTO stocks."Matiere"
           ("Id_Matière","Quantite_commande_(kg)","Quantite_casse_(kg)","Quantite_Sortie_(kg)")
    VALUES (id, 0, 0, -(NEW."Quantite"));
  END IF;

  RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql';

Évidemment, ça ne marchera pas car la clause WHERE "Nom_Prod_Fini"."Nom_Produit" = "Nom_Produit" est toujours vrai (colonne X = colonne X, ça peut pas être faux...). Et comme je ne sais pas d'où il vient (peut-être de la ligne NEW ?)...


Guillaume.

Hors ligne

#3 23/06/2010 19:13:30

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

Bonsoir gleu,

Plus précisément, j'ai une table "Calculs".

J'entre toutes les informations, dont le nom du produit. Ce nom de produit contient un id matière et un id pot. Ces deux dernières info figurent sur une autre table.

Il y a donc trois tables qui entrent en interaction.

Ce que je souhaite, c'est que quand je valide ma table "Calculs", il mette à jour une autre colonne d'une autre table. Cette autre table n'est autre que ma table de stocks.
Ainsi, pour un produit donné dans calcul, les composants vont mettre à jour les tables matiere et pot.

Et je bloque lamentablement dessus.

Je vais essayer votre code,

A tout à l'heure,

LeHibou

PS: au temps pour moi. dans

WHERE "Nom_Prod_Fini"."Nom_Produit" = "Nom_Produit"

il faut en fait lire

WHERE "Nom_Prod_Fini"."Nom_Produit" = "Nom_Produit_Fini"

Cette valeur est différente. Sinon effectivement, aucun intérêt à faire une égalité.

A tout à l'heure

Dernière modification par LeHibou (23/06/2010 19:16:10)

Hors ligne

#4 23/06/2010 19:36:05

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

Mon égalité avec le where ne donne rien; Ce qu'il faut pourtant, c'est que la requête s'effectue sur le produit sélectionné dans la table "Calculs".

Voici mon trigger réécrit:

Declare
Id integer;

Begin
select into id "Id_Matiere"
from "Facturation"."Nom_Prod_Fini"
where "Nom_Prod_Fini"."Nom_Produit"="Nom_Produit_Fini";

	If (TG_OP = 'INSERT')
		Then insert into stocks."Matiere" ("Id_Matière","Quantite_commande_(kg)","Quantite_casse_(kg)","Quantite_Sortie_(kg)")
		Values (id,0,0,-(new."Quantite"));
		Return new;

	end if;
	return new;

	
End;

je mets également les extraits de tables concernées (sans contraintes, etc...):

Table Calculs:

CREATE TABLE "Facturation"."Calculs"
(
  "Prix_HT" numeric NOT NULL,
  "Remise(%)" numeric,
  "Quantite" numeric,
  "Prix_Net_HT" numeric(30,2),
  "Nom_Produit_Fini" character varying NOT NULL,
  "Tva-type" integer,
  "Valeur_Tva" numeric NOT NULL,
  "Montant_tva" numeric(30,2),
  "Num_Id" integer,
  "Montant_Ligne" numeric(30,2),
  "Num_Ope" integer NOT NULL DEFAULT nextval('"Facturation"."Num_ope_seq"'::regclass),
  "Type_facture" character varying,

Nom_Produit_Fini est lié à cette table:

CREATE TABLE "Facturation"."Nom_Prod_Fini"
(
  "Nom_Produit" character varying NOT NULL,
  "Id_Matiere" integer,
  "Id_Pot" integer,

et la table de stock est la suivante:

CREATE TABLE stocks."Matiere"
(
  "Id_Matière" integer NOT NULL,
  "Quantite_commande_(kg)" numeric,
  "Quantite_casse_(kg)" numeric,
  "Quantite_Sortie_(kg)" numeric,
  "Quantite_finale_(kg)" numeric,
  "Date" timestamp with time zone,

Le message d'erreur est le suivant:

ERROR:  missing FROM-clause entry for table "Calculs"
LINE 1: ...turation"."Nom_Prod_Fini" where "Nom_Prod_Fini" = "Calculs"....

Dernière modification par LeHibou (23/06/2010 19:51:28)

Hors ligne

#5 23/06/2010 20:09:34

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

C'est bon, cela fonctionne. Je laisse à tous le trigger qui renvoit le résultat dans une colonne. Cela peut servir à d'autres.

Voici donc la solution pour que cela marche:

Declare
Id integer;

Begin
select into id "Id_Matiere"
from "Facturation"."Nom_Prod_Fini"
where "Nom_Prod_Fini"."Nom_Produit"= new."Nom_Produit_Fini";

    If (TG_OP = 'INSERT')
        Then insert into stocks."Matiere" ("Id_Matière","Quantite_commande_(kg)","Quantite_casse_(kg)","Quantite_Sortie_(kg)")
        Values (id,0,0,-(new."Quantite"));
        Return new;

    end if;
    return new;

    
End;

Merci à vous gleu.

Hors ligne

#6 23/06/2010 20:22:33

gleu
Administrateur

Re : Trigger qui récupère les valeurs induites

Impossible de vous aider quand le message d'erreur ne correspond en rien à la fonction que vous donnez.


Guillaume.

Hors ligne

#7 23/06/2010 22:35:02

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

J'entends bien gleu,

Je perçois que mon "Merci à vous gleu." pouvait être mal interprété et c'est ma faute.
Il aurait été plus judicieux d'écrire : "ne vous en faites pas, c'est bon, j'avais mal écrit le code. Mais j'ai trouvé à présent."

En tout cas, je vous remercie puisque vous m'avez mis sur la voie avec la fonction.

A bientôt!

Hors ligne

#8 23/06/2010 23:19:16

gleu
Administrateur

Re : Trigger qui récupère les valeurs induites

Euh, non, désolé, j'ai écris ma réponse sans voir votre réponse de 20h09. Ma faute.


Guillaume.

Hors ligne

#9 24/06/2010 08:36:13

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

Bonjour,

J'ai tenté une nouvelle chose: faire en sorte que le trigger se déclenche si une valeur est sélectionnée dans "Calculs"."Type_facture": j'ai donc edité la ligne du If mais j'ai un message d'erreur:

If ("Type_facture" = 'Facture' or "Type_facture" = 'Acompte', TG_OP = 'INSERT')

qui donne:
ERROR:  column "Type_facture" does not exist

Si j'ajoute le "Calculs". devant, il me dit qu'il manque une clause "FROM".
Je me suis pourtant renseigné sur les conditions de type IF(expr1,expre2,expre3). Même en supprimant le OR, je n'ai rien de bon...

Pourquoi? je pose pourtant bien les bases de la condition non?

A bientôt,

LeHibou

Hors ligne

#10 24/06/2010 10:24:17

gleu
Administrateur

Re : Trigger qui récupère les valeurs induites

Je ne vois pas où vous avez trouvé une expression du type IF(expr1,expre2,expre3) dans la documentation de PostgreSQL. Ça n'existe pas.

À priori, vous avez l'air de vouloir faire quelque chose comme ça :

IF ((NEW."Type_facture" = 'Facture' OR NEW."Type_facture" = 'Acompte') AND TG_OP = 'INSERT')

Guillaume.

Hors ligne

#11 24/06/2010 10:53:49

LeHibou
Membre

Re : Trigger qui récupère les valeurs induites

Ok... ça marche.

Mots-clé: trigger, valeurs, agir, conditions,
Je résume pour les autres (gain de temps notable pour tous et évitement des doublons ultérieurs):

Trigger sur lequel on fait une sélection d'une valeur induite par celle d'un autre: voir #5, le code est complet. Reste à l'adapter à votre cas.

Le trigger ci dessous permet de vérifier un/des champs et lance le trigger si ils sont vérifiés. Le voici en entier:

Declare
id integer;

Begin
select into id "Id_Matiere"
from "Facturation"."Nom_Prod_Fini"
where "Nom_Produit" = new."Nom_Produit_Fini";


	If ((NEW."Type_facture" = 'Facture' OR NEW."Type_facture" = 'Acompte') AND TG_OP = 'INSERT') 
		Then insert into stocks."Matiere" ("Id_Matière","Quantite_commande_(kg)","Quantite_casse_(kg)","Quantite_Sortie_(kg)")
		Values (id,0,0,new."Quantite"); -- ici, ne vous fiez pas à ce qu'il y a entre parenthèses. Adaptez-le selon l'ordre des champs de votre table et ce que vous voulez faire--
		Return new;

	end if;
	return new;

	
End;

Voilà bonne journée à tous, et encore une fois, merci à vous gleu,

A bientôt,

LeHibou

Dernière modification par LeHibou (24/06/2010 10:55:18)

Hors ligne

Pied de page des forums