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 10/10/2009 12:43:50

flotho
Membre

RECORD et PLPGSQL

Bonjour à toutes et à tous,

Merci d'abord de la réponse rapide à mon premier post.

J'ai une question plus simple.
J'ai ouvert une boucle en FOR et je manipule un objet RECORD dans ma boucle. Est il possible de mettre à jour l'un des champs sans être obligé de repasser par définition d'un curseur, ou bien est il possible d'accéder au curseur implicitement ouvert dans la boucle?

Merci d'avance de vos réponses.

Hors ligne

#2 10/10/2009 13:30:51

Marc Cousin
Membre

Re : RECORD et PLPGSQL

La réponse est là :

http://docs.postgresql.fr/8.4/plpgsql-cursors.html

Il faut utiliser le WHERE CURRENT OF. Je ne crois pas qu'on puisse modifier le contenu du curseur pour modifier la table.


Marc.

Hors ligne

#3 10/10/2009 13:53:04

flotho
Membre

Re : RECORD et PLPGSQL

Bonjour et merci de votre réponse.

Je connais bien cela mais comme j'ai un code comme cela :

FOR document_local in (select * from document) LOOP
END LOOP;

Je m'étais dis que je pouvais changer une valeur à l'aide du curseur implicite de la boucle for ou bien au travers du record "document".

Mais apparemment je ne peux pas affecter une valeur à un champ d'un record, je n'y ai accès qu'en lecture.
Pour l'écriture je vais être obligé de repasser par le curseur.

HORRIBLE CONSTAT, la syntaxe que vous me proposez ne fonctionne pas avec la version 8.3 de pg mais seulement avec la 8.4.
Je vais donc faire des arabesques dans mon code

Merci encore

Dernière modification par flotho (10/10/2009 14:24:48)

Hors ligne

#4 03/02/2010 01:58:48

flotho
Membre

Re : RECORD et PLPGSQL

Re bonjour,

J'ai toujours le même problème mais cette fois ci sur une base 8.4.
Voici la tête de mon trigger :

FOR ventilation_local IN (SELECT * FROM XXX) LOOP
    IF (mytest) THEN
        ventilation_local.myfield := mynewvalue;
    END IF;
END LOOP;

d'après la doc : http://docs.postgresql.fr/8.4/plpgsql-statements.html
l'affectation de valeur sur un record devrait être opérationnelle.

Pourtant, le champ myfield ne prend pas la valeur mynewvalue qui est non nulle et de même type. J'ai même essayé de mettre une valeur fixe.

Merci d'avance de votre aide

Hors ligne

#5 03/02/2010 02:18:55

flotho
Membre

Re : RECORD et PLPGSQL

J'ai fait un test supplémentaire :

FOR ventilation_local IN (SELECT * FROM XXX) LOOP 
     IF (mytest) THEN  
          RAISE NOTICE 'ventilation %',  ventilation_local;
          ventilation_local.myfield:=10;   
          RAISE NOTICE 'ventilation %',  ventilation_local;
      END IF;
END LOOP;

Les deux RAISE me renvoie des résultats adpatés, j'entends par là que la serie de valeur avant est différente de celle d'après.

Mais dès que je sors de la boucle, l'enregistrement n'est pas validé!!

Hors ligne

#6 03/02/2010 08:14:35

Marc Cousin
Membre

Re : RECORD et PLPGSQL

Le record n'est qu'une recopie de l'enregistrement, ce n'est pas l'enregistrement lui même. Pour le modifier vous devez faire un update.

Si votre trigger est un trigger BEFORE, vous avez accès aux records implicites OLD et NEW, qui contiennent l'enregistrement avant modification par le trigger, et après modification par le trigger. Je ne comprends pas pourquoi dans le code d'un trigger vous auriez une boucle FOR sur toute une table. Votre trigger est bien sur la table XXX ?
Si oui, et que vous voulez juste que le champ myfield vaille 10 dans le cas de votre test, votre code deviendrait :

IF (mytest) THEN  
          NEW.ventilation_local.myfield:=10;   
      END IF;
END LOOP;

En écrivant mytest pour qu'il travaille sur NEW, bien sûr…

http://docs.postgresql.fr/8.4/triggers.html

PS: ça serait certainement plus simple pour vous à expliquer et pour nous à comprendre si on travaillait sur du vrai code… plutot que d'appeler les tables XXX, les tests mytest, etc…

Dernière modification par Marc Cousin (03/02/2010 08:15:48)


Marc.

Hors ligne

#7 03/02/2010 11:36:40

flotho
Membre

Re : RECORD et PLPGSQL

Marc Cousin a écrit :

Le record n'est qu'une recopie de l'enregistrement, ce n'est pas l'enregistrement lui même. Pour le modifier vous devez faire un update.

Définitivement je vais l'imprimer en grand sur mon mur!!
A chaque fois que je développe des triggers de plus de 10 lignes, je retrouve des réflexes de développeur et oublie les bases de la BDD.

Marc Cousin a écrit :

Si votre trigger est un trigger BEFORE, vous avez accès aux records implicites OLD et NEW, qui contiennent l'enregistrement avant modification par le trigger, et après modification par le trigger.

Complètement acquis

Marc Cousin a écrit :

Je ne comprends pas pourquoi dans le code d'un trigger vous auriez une boucle FOR sur toute une table.
Votre trigger est bien sur la table XXX ?

Tout à fait. En fait je ne rebalaye pas toute la table mais seulement les lignes qui ont un certain critère commun avec celui qui est inséré. C'est pour faire de la ventilation analytique comme vous vous en doutez!

Marc Cousin a écrit :

PS: ça serait certainement plus simple pour vous à expliquer et pour nous à comprendre si on travaillait sur du vrai code… plutot que d'appeler les tables XXX, les tests mytest, etc…

Promis la prochaine fois je mets le tout!

Merci en core de vos conseils avisés.

Hors ligne

#8 03/02/2010 13:03:00

Marc Cousin
Membre

Re : RECORD et PLPGSQL

Ok. Si vous en avez la possibilité, passez en 8.4, le WHERE CURRENT OF simplifie bien le code, et est meilleur en termes de performances…


Marc.

Hors ligne

#9 03/02/2010 13:10:27

flotho
Membre

Re : RECORD et PLPGSQL

Je suis en 8.4.

Dès que j'airais le temps, je me repencherai sur le WHERE CURRENT OF

Merci pour tout

Hors ligne

Pied de page des forums