#1 Mon 16 July 2012 07:58
- hyasinthe9
- Participant occasionnel
- Lieu: Madagascar
- Date d'inscription: 29 Jun 2012
- Messages: 21
PL/pgSQL
Bonjour tout le monde,
Je crée maintenant des fonction PL/pgSQL.
Mais je suis bloqué au niveau de création de type.
En fait ma question est: est-il possible de créer un type "table"? Si c'est possible, comment?
Merci!
Hors ligne
#2 Mon 16 July 2012 10:29
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: PL/pgSQL
Bonjour.
Oui c'est possible:
Code:
create table ...
Nicolas
Hors ligne
#3 Mon 16 July 2012 13:57
- Squid
- Participant actif
- Date d'inscription: 2 Apr 2010
- Messages: 109
Re: PL/pgSQL
Il y a le type name.
name 64 octets type interne pour les noms d'objets
http://docs.postgresql.fr/8.1/datatype-character.html
Ainsi que character varying/text dans des EXECUTE 'Requête dynamique avec concaténation' || variable_text || ' fin de requête' ;
Hors ligne
#4 Mon 16 July 2012 15:53
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: PL/pgSQL
pardon, j'ai lu un peu vite la question.
Il y a plusieurs types permettant le stockage de plusieurs colonnes, si c'est bien cela que vous voulez faire.
Vous pouvez definir une table avant l'appel de la fonction et utiliser le nom de table comme nouveau type.
Vous pouvez egalement utiliser le type RECORD, non nommé, mais qui obligera ensuite a nommer les colonnes lors de l'appel de la fonction.
(je remets ici le liens vers la doc pl/pgsql qui présente une bonne introduction du langage et des types de données: http://www.postgresql.org/docs/9.1/inte … gsql.html)
Nicolas
Hors ligne
#5 Mon 16 July 2012 16:59
- hyasinthe9
- Participant occasionnel
- Lieu: Madagascar
- Date d'inscription: 29 Jun 2012
- Messages: 21
Re: PL/pgSQL
Merci de votre réponse,
En fait j'ai déjà lu ce tutoriel.Mais je voudrais programmer une fonction qui prend comme paramètre des tables.
Voici un exemple simple(NB:ce code ne fonctionne pas):je voudrais afficher les contenues d'une table quelconque.
Code:
CREATE OR REPLACE FUNCTION "teste"(obj name) RETURNS SETOF name AS $BODY$ BEGIN RETURN QUERY SELECT * FROM "obj" ; END $BODY$ LANGUAGE plpgsql VOLATILE
Le paramètre obj représente les tables.
En m'aidant vous pouvez corriger ce code.
Merci encore de vos précieuse réponses.
Hors ligne
#6 Mon 16 July 2012 17:20
- Squid
- Participant actif
- Date d'inscription: 2 Apr 2010
- Messages: 109
Re: PL/pgSQL
Est-ce que cela vous aide?
http://www.linuxscrew.com/2009/07/03/po … w-columns/
SELECT * FROM information_schema.columns WHERE table_name ='table'
Hors ligne
#7 Tue 17 July 2012 10:19
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: PL/pgSQL
Merci de votre réponse,
En fait j'ai déjà lu ce tutoriel.Mais je voudrais programmer une fonction qui prend comme paramètre des tables.
Voici un exemple simple(NB:ce code ne fonctionne pas):je voudrais afficher les contenues d'une table quelconque.Code:
CREATE OR REPLACE FUNCTION "teste"(obj name) RETURNS SETOF name AS $BODY$ BEGIN RETURN QUERY SELECT * FROM "obj" ; END $BODY$ LANGUAGE plpgsql VOLATILELe paramètre obj représente les tables.
En m'aidant vous pouvez corriger ce code.
Merci encore de vos précieuse réponses.
Bonjour,
dans ce contexte, non, il n'y a pas de type representant une table. Il faut passer le nom de la table sous forme de texte, puis générer la requete dynamiquement:
Code:
CREATE OR REPLACE FUNCTION teste (text name) RETURNS SETOF record AS $BODY$ BEGIN RETURN EXECUTE 'SELECT * FROM ' || quote_ident(name); END $BODY$ LANGUAGE plpgsql VOLATILE
(pas testé)
Deux remarques:
• En SQL, les chaines de texte sont mises en guillemets simples 'texte' et non "double".
• J'eviterai de mettre le nom de la fonction entre guillements double (FUNCTION "teste"): ca vous obligera par la suite a toujours utiliser le nom en minuscule.
Ici dans la doc pg: http://www.postgresql.org/docs/9.1/inte … CUTING-DYN
Nicolas
PS. Vous etes sur d'avoir besoin d'une fonction qui ne fait qu'une select * from table ?
Hors ligne
#8 Wed 18 July 2012 09:39
- hyasinthe9
- Participant occasionnel
- Lieu: Madagascar
- Date d'inscription: 29 Jun 2012
- Messages: 21
Re: PL/pgSQL
Bonjour Nicolas Ribot,
En faite je n'ai pas besoin de cette fonction,seulement je voulais comprendre comment,après sélection de la fonction, introduire un paramètre "nom_table".
Je viens d'essayer votre code ci-dessus mais ça ne marche pas encore.
SVP Nicolas Ribot,j'ai encore besoin de votre aide en corrigeant ce qui va suivre:
Code:
CREATE OR REPLACE FUNCTION "AA_fh_Merge_table2_into_table1"() RETURNS void AS $BODY$ DECLARE toto CURSOR FOR (SELECT * FROM "table2") ; n integer; m integer; resultat RECORD; a integer:=0; BEGIN n:=(SELECT count(*) FROM "table1"); m:=(SELECT count(*) FROM "table2"); a:=n; OPEN toto; -- ouvrir le cursor FOR I IN 1..m LOOP a:=a+1; --MOVE NEXT FROM toto; FETCH toto INTO resultat; -- fetch une ligne dans un record UPDATE "table2" SET id=a WHERE CURRENT OF toto; END LOOP; CLOSE toto; -- fermer le cursor INSERT INTO "table1" SELECT * FROM "table2"; END$BODY$ LANGUAGE plpgsql VOLATILE
Ce code permet de merger les contenues de la table "table2" dans "table1" en evitant le doublon des valeurs de "id".
Mais mon problème se situe au niveau de nom de table.En effet ce fonction permet de merger seulement "table2" dans "table1".
Et si je voudrai mereger deux autre table, ex: merger "table4" dans "table3". Comment dois je paramétrer ma fonction.
NB:Je crée ma fonction à partir de "pgAdminIII" et je la sélectionne à partir du panneau SQL de ce dernier.
pgAdminIII met automatiquement le guillemet au nom de fonction (FUNCTION "teste").Je ne sais pas encore comment l'enlever.
Hors ligne
#9 Wed 18 July 2012 11:22
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1554
Re: PL/pgSQL
Bonjour,
Vous pouvez ecrire votre fonction avec un editeur de texte autre que pgAdmin, ce qui vous permettra de controler exactement le format de ce que vous ecrivez.
N'ayant pas trop le temps, voici un petit exemple de fonction prenant un nom de table et listant son contenu:
Code:
create or replace function test(nom text) returns setof record as $$ DECLARE BEGIN RETURN QUERY EXECUTE 'select * from '||quote_ident(nom); END; $$ LANGUAGE plpgsql;
Son appel se fait ainsi (la table img existe chez moi et a la structure suivante:
Code:
Table "public.img" Column | Type | Modifiers --------+---------+-------------------------------------------------- id | integer | not null default nextval('img_id_seq'::regclass) file | text | ) select * from test('img') as foo (id integer, file text);
Comme vous le voyez, il faut nommer le resultat de la fonction, puisque elle est déclarée retournant un RECORD, qui n'est pas un vrai type. Il faut donc "creer" la table representant le resultat au moment de la requete. (d'autres solutions consistent a utiliser des parametres OUT, ou de creer avant un type correspondant a la table)
Nicolas
Hors ligne
#10 Thu 19 July 2012 14:43
- hyasinthe9
- Participant occasionnel
- Lieu: Madagascar
- Date d'inscription: 29 Jun 2012
- Messages: 21
Re: PL/pgSQL
Merci Beaucoup,grâce à vous je sais maintenant programmer une fonction dont les paramètre sont des "Tables".
Voici mes codes:
Code:
CREATE OR REPLACE FUNCTION "AA_fh_merger_final"(ma_tab_1 text, ma_tab_2 text) RETURNS void AS $BODY$ DECLARE toto refcursor; n integer; m integer; resultat RECORD; a integer:=0; BEGIN BEGIN EXECUTE 'SELECT count(*) FROM'||ma_tab_1::regclass INTO n; EXECUTE 'SELECT count(*) FROM'||ma_tab_2::regclass INTO m; END; a:=n; OPEN toto FOR EXECUTE 'SELECT * FROM ' ||ma_tab_2::regclass; --quote_ident(ma_tab_2); -- ouvrir le cursor FOR I IN 1..m LOOP a:=a+1; --MOVE NEXT FROM toto; FETCH toto INTO resultat; -- fetch une ligne dans un record EXECUTE 'UPDATE ' ||ma_tab_2::regclass|| ' SET ' ||'id' ||'=' ||a || 'WHERE CURRENT OF toto'; END LOOP; CLOSE toto; -- fermer le cursor EXECUTE 'INSERT INTO' ||ma_tab_1::regclass|| 'SELECT * FROM' ||ma_tab_2::regclass; END$BODY$ LANGUAGE plpgsql VOLATILE
Une dernière question sur ce sujet:Pourquoi le ligne suivante ne marche pas.
Code:
EXECUTE 'UPDATE ' ||ma_tab_2::regclass|| ' SET ' ||'id' ||'=' ||a || ' WHERE CURRENT OF toto';
(voir 23ème ligne)
Dernière modification par hyasinthe9 (Fri 20 July 2012 17:34)
Hors ligne