Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Printemps des cartes 2024

#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: 1537

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: 1537

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: 1537

Re: PL/pgSQL

hyasinthe9 a écrit:

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.


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: 1537

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

 

Pied de page des forums

Powered by FluxBB