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 31/10/2013 11:03:09

amelo
Membre

Copie de colonnes d'un row selon valeurs colonnes du row cible

Bonjour,


Je simplifie la difficulté que je rencontre en prenant pour exemple une table nommée arret, comportant les colonnes suivantes arret_id (integer), arret_phase (integer), arret_poly_id (integer), arret_info (character)


Je souhaiterais qu'à l'ajout d'un enregistrement dans cette table un trigger se déclenche pour contrôler si il n'existe pas déjà des enregistrements avec la même valeur de arret_poly_id et le cas échéant qu'il remplisse le champ arret_info avec la valeur arret_info de l'enregistrement ayant la même valeur de arret_poly_id et la plus grande valeur de arret_phase.


Voilà ce que j'ai déjà codé :
   

CREATE OR REPLACE FUNCTION arret_insert_func()
  RETURNS trigger AS
$BODY$BEGIN

IF new.arret_poly_id = arret_poly_id THEN
	UPDATE arret SET(new.arret_phase, new.arret_info)
		SELECT MAX( arret_phase )+1, arret_info
			FROM arret 
			WHERE arret_poly_id = new.arret_poly_id
			GROUP BY arret_poly_id, arret_phase, arret_info ;
END IF;

RETURN NEW;
END;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION arreteinsert_func()
  OWNER TO me;
  
CREATE TRIGGER arret_insert
  AFTER INSERT
  ON arret
  FOR EACH ROW
  EXECUTE PROCEDURE arret_insert_func();

Cette fonction renvoie une erreur, elle ne reconnait pas la colonne arret_poly_id. Je pense qu'il faudrait que j'utilise une boucle for mais je n'en ai jamais utilisée et suis un peu perdue du coup.
 
Pour être plus compréhensible voici un exemple: 


arret_id    arret_phase    arret_poly_id    arret_info
1                    1                    100             blabla
2                    1                    200             blublu
3                    2                    100             bloblo
4                    1                    300             blibli


Avec les valeurs suivantes, l'ajout d'un enregistrement ayant comme valeur arret_poly_id =100 complèterait les champs arret_info et arret_phase avec les valeurs respectives bloblo et 3.



En espérant trouver de l'aide,

Amélie

Hors ligne

#2 31/10/2013 15:56:49

gleu
Administrateur

Re : Copie de colonnes d'un row selon valeurs colonnes du row cible

Il faut en effet exécuter une boucle FOR du style :

FOR variable in SELECT ...
LOOP

END LOOP

Dans la boucle, il faut intégrer les modifications dans la ligne pointée par la variable NEW.


Guillaume.

Hors ligne

#3 08/11/2013 11:07:38

amelo
Membre

Re : Copie de colonnes d'un row selon valeurs colonnes du row cible

Bonjour,
Voici ce que j'ai mis en place. Je ne sais pas si c'est la meilleure solution mais en tout cas ça fonctionne :

CREATE OR REPLACE FUNCTION arret_insert_func()
  RETURNS trigger AS
$BODY$

DECLARE
	s RECORD ;
	cur CURSOR FOR SELECT DISTINCT ON (arret_poly_id) arret_poly_id, arret_phase, arret_info
			FROM arret
			ORDER BY arret_poly_id, arret_phase DESC;  
 
BEGIN
	OPEN cur;
	
	LOOP
		FETCH NEXT FROM cur INTO s;
		EXIT WHEN NOT FOUND;
		IF new.arret_poly_id = s.arret_poly_id THEN
			new.arret_info := s.arret_info ; 
		END IF;
	END LOOP;
	
	CLOSE cur;
	RETURN new;
END;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION domaine_public.arret_insert_func()
  OWNER TO me;


CREATE TRIGGER arret_insert
  BEFORE INSERT
  ON arret
  FOR EACH ROW
  EXECUTE PROCEDURE arret_insert_func();

(A noter que le calcul du champs arret_phase s'effectue préalablement et n'est plus codé dans cette fonction)

Amélie

Dernière modification par amelo (08/11/2013 11:08:01)

Hors ligne

#4 09/11/2013 18:10:34

gleu
Administrateur

Re : Copie de colonnes d'un row selon valeurs colonnes du row cible

C'est l'idée, même si je l'aurais codé plutôt ainsi :

CREATE OR REPLACE FUNCTION arret_insert_func()
  RETURNS trigger AS
$BODY$

DECLARE
	p_arret_poly_id arret.arret_poly%TYPE;
	p_arret_phase arret.arret_phase%TYPE;
	p_arret_info arret.arret_info%TYPE;
 
BEGIN
	FOR p_arret_poly_id, p_arret_phase, p_arret_info IN
		SELECT DISTINCT ON (arret_poly_id) arret_poly_id, arret_phase, arret_info
			FROM arret
			ORDER BY arret_poly_id, arret_phase DESC
	
	LOOP
		IF new.arret_poly_id = p_arret_poly_id THEN
			new.arret_info := p_arret_info ; 
		END IF;
	END LOOP;
	
	RETURN new;
END;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Guillaume.

Hors ligne

Pied de page des forums