Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
Pages : 1
#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
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.
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
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!
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
Pages : 1