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 PL/pgSQL » fonction qui renvoie une table » 20/02/2017 06:54:13

Sadewizz
Réponses : 2

Bonjour,

je fais actuellement face à un soucis.
Je possède une table "source" qui contient des lignes que je dispatche par la suite dans d'autres tables via un attribut spécifique.

Ce que j'essaie d'avoir, c'est une comparaison entre ce qui existe dans la table source, et ce qui est exporté dans les autres tables afin de voir si il n'y a pas d'oublie (question de paranoïa).

la requête ci dessous me donne bien ce que je cherche mais uniquement entre deux tables (la table source et une seul table de dispatche):

select 
matable1.plandxf as plandxf, 
count(distinct matable1.gid) as table_destination, 
count(distinct matable2.gid) as table_source 
from monschema.matable1 
left join monschema.matable2 
on matable2.plandxf=matable1.plandxf 
group by matable1.plandxf

le résultat en sortie:

plandxf   table_destination  table_source
--------  -----------------  -------------
ACCEHAND  2112               2112         
GUE       59                 59
PASSEREL  773                773

j'ai donc essayé de créer une fonction qui me permettrais de factoriser cette requête et ainsi de comparer ma table source à toute mes tables de dispatches et qu'elle me sorte un tableaux similaire au précédent.
Je pourrais ainsi récupérer le résultat de cette requête via un autre logiciel métier.

Voici ma "fonction" actuelle. Elle ce lance mais ne ressort pas de résultat ni de tableaux...

CREATE OR REPLACE FUNCTION monschema.sig_count3()
  RETURNS TABLE(plandxf character varying, table character varying, c character varying) AS
$BODY$
DECLARE
liste RECORD;
BEGIN	

	FOR liste IN (select tablename from pg_tables where tablename = 'matable1')
	LOOP
	execute'select '
		||liste.tablename||'.plandxf as plandxf, 
		count(distinct '||liste.tablename||'.gid) as table_destination, 
		count(distinct matable2.gid) as table_source from monschema.'||liste.layer||' 
		left join monschema.matable2 
		on matable2.plandxf='||liste.tablename||'.plandxf 
		group by '||liste.tablename||'.plandxf;';
	END LOOP;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION monschema.sig_count3()
  OWNER TO postgres;

Si quelqu'un à la solution, je suis preneur wink
Merci à vous ^^

Sadewizz

#2 Re : PL/pgSQL » Trigger sur une vue » 17/06/2014 09:06:25

Bonjour Geo-x,

Merci pour votre réponse.
Effectivement le trigger n'agit pas sur la bonne fonction. J'ai vraisemblablement fais une erreur lors de mon copier coller.
Mon but était d'avoir une souche d'intersection dynamique. De ce fait une vue me semblait répondre au problème, cependant j'ai pu observer une certaine lenteur lors de l'import de cette vue dans mon client carto. Alors qu'il n'y a que 74 lignes. La même couche mais cette fois ci en table, s'importe sans problème.
Avez vous une idée sur le pourquoi de cette lenteur?

Sadewizz

#3 PL/pgSQL » Trigger sur une vue » 12/06/2014 11:22:54

Sadewizz
Réponses : 3

Bonjour,

Est il possible d'implémenter une table  en effectuant une requête via un trigger, sur des données issues d'une vue ?

J'ai pour l'instant cette fonction

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

INSERT INTO za SELECT row_number() OVER (ORDER BY france_littoral.id) AS gid,
new.table_liste_emprise.nom_donnee,
france_littoral.id AS zone,
france_littoral.the_geom_wgs84
FROM france.france_littoral,
france.table_liste_emprise
WHERE st_intersects(france_littoral.the_geom_wgs84, table_liste_emprise.the_geom_wgs84);
RETURN NEW;
return null;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION za()
  OWNER TO postgres;
------------------------------------------------------------------------
CREATE TRIGGER zone_geo
INSTEAD OF INSERT ON zone_geographique
FOR EACH ROW
EXECUTE PROCEDURE za();

Ici, j'essaie de réaliser la requête en fonction des nouveaux ajouts dans la vue "table_liste_emprise", et d'implémenter le résultat dans la table "za".
Cependant le trigger ne marche pas alors que le code s’exécute bien.
D'ou ma question : Est ce possible de réaliser ce genre d'opération ?
Merci d'avance.

Sadewizz

#4 Re : PL/pgSQL » supression des double guillemets dans le résultat d'une fonction. » 06/06/2014 11:36:08

Bonjour,

Merci pour votre réponse. J'ai suivi vos conseils et j'ai utilisé la fonction LOWER pour changer le contenu du deuxième record (geom)

 FOR geom IN SELECT LOWER(type) FROM geometry_columns where f_table_schema='france' AND f_table_name = liste.tablename

Cela fonctionne parfaitement. Merci pour votre aide!!
Bonne journée.

Sadewizz

#5 PL/pgSQL » supression des double guillemets dans le résultat d'une fonction. » 04/06/2014 16:54:39

Sadewizz
Réponses : 2

Salut,

J'ai récemment essayer de créer une fonction me permettant de mettre à jour chaque table lors de son insertion dans la base de donnée.
Cependant j'ai un soucis, lorsque je lui dis de créer une nouvelle colonne géométrique. Il faut lui spécifier le type de géométrie de la couche, ce que je fais. Mais le problème est que le type ressort avec un double guillemets.
Voici mon code. L'erreur survient au premier "execute" à la ligne 18.

CREATE OR REPLACE FUNCTION france.maj_2()
  RETURNS void AS
$BODY$
DECLARE
    liste RECORD;
    geom RECORD;
BEGIN
    FOR liste IN SELECT tablename FROM pg_tables where tablename 
		 IN 
		(select tablename from pg_tables where schemaname ='france' and tablename in 
		(SELECT f_table_name FROM geometry_columns 
		where f_table_name not like 'france_littoral'))
    loop
      FOR geom IN SELECT type FROM geometry_columns where f_table_schema='france' AND f_table_name = liste.tablename
      loop
    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'france' AND TABLE_NAME = liste.tablename AND COLUMN_NAME = 'the_geom_wgs84')
THEN 
    execute'select addgeometrycolumn ('''','''||quote_ident(liste.tablename)||''',''the_geom_wgs84'',''4326'','''||quote_ident(geom.type)||''',2);
           update '||quote_ident(liste.tablename)||' set the_geom_wgs84= st_transform(the_geom_orig,4326);';
    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'france' AND TABLE_NAME = liste.tablename AND COLUMN_NAME = 'nom_donnee')
THEN 
    execute'ALTER TABLE '||quote_ident(liste.tablename)||' ADD COLUMN nom_donnee varchar(80);
	   update '||quote_ident(liste.tablename)||' set nom_donnee='''||quote_ident(liste.tablename)||''';';
    IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'france' AND TABLE_NAME = liste.tablename AND COLUMN_NAME = 'id')
THEN
    execute'ALTER TABLE '||quote_ident(liste.tablename)||' ADD COLUMN id varchar(80);
           ALTER TABLE '||quote_ident(liste.tablename)||' drop constraint '||quote_ident(liste.tablename)||'_pkey;
           UPDATE '||quote_ident(liste.tablename)||' set id = nom_donnee||''_''||nextval(''france.id_seq''::regclass);
           ALTER TABLE '||quote_ident(liste.tablename)||' add constraint '||quote_ident(liste.tablename)||'_pkey primary key(id);';
    end if;
    end if;
    end if;
    end loop;
    end loop; 
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION france.emprise_table()
  OWNER TO postgres;
 

Il me sort donc l'erreur suivante :

ERREUR:  la colonne « POINT » n'existe pas
LINE 1: ...addgeometrycolumn ('','b','the_geom_wgs84','4326',"POINT",2)...
                                                             ^
QUERY:  select addgeometrycolumn ('','b','the_geom_wgs84','4326',"POINT",2);
           update b set the_geom_wgs84= st_transform(the_geom_orig,4326);
CONTEXT:  fonction PL/pgsql maj_2(), ligne 16 à instruction EXECUTE
********** Erreur **********

ERREUR: la colonne « POINT » n'existe pas
État SQL :42703
Contexte : fonction PL/pgsql maj_2(), ligne 16 à instruction EXECUTE

D'après vous, comment puis je retirer ces doubles guillemets? Avez vous une idée?
Merci pour vos éventuelles réponses et bonne soirée (ou journée pour certains) ;D

Sadewizz.

#6 Re : Général » Fonction permettant de créer de générer des tables » 03/06/2014 09:30:59

Bonjour,

Oui effectivement, j'ai entre temps changé le nom de la fonction désolé. Mais l'erreur reste la même.
J'ai néanmoins réussi à résoudre mon problème.

CREATE OR REPLACE FUNCTION france.emprise_table()
  RETURNS void AS
$BODY$
DECLARE
    liste RECORD;
    rec RECORD;
    curs refcursor;
BEGIN
   FOR liste in select nom_donnee FROM france.table_liste
   LOOP
    EXECUTE 'CREATE or replace view france.'||quote_ident(liste.tablename)||'_emp AS 
    SELECT nom_donnee, st_convexhull( st_collect (the_geom_wgs84)) as the_geom_wgs84
    FROM '||quote_ident(liste.tablename)||' group by nom_donnee;';
    END LOOP; 
  OPEN curs FOR SELECT nom_donnee FROM table_liste;   
    LOOP
        FETCH curs INTO rec;
        exit when not found;
    END LOOP;
   CLOSE curs;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION france.emprise_table()
  OWNER TO postgres; 

A priori il manquait des LOOP et certains étaient mal placés.
Merci pour vos aides.

Sadewizz

#7 Re : Général » Fonction permettant de créer de générer des tables » 02/06/2014 11:22:44

Merci pour votre réponse, et l'intérêt porté à mon post.
J'ai suivi vos conseils et j'ai commencé par réaliser une fonction que j’appellerais ensuite dans le trigger de la table en question.
Seulement pg_admin me retourne erreur que je ne comprend pas lorsque j'appel ma fonction avec un select * from mafonction().

Voici ma fonction:

 CREATE OR REPLACE FUNCTION france.emprise_table() RETURNS void AS $$
DECLARE
    liste RECORD;
    rec RECORD;
    curs refcursor;
BEGIN
    FOR liste in select nom_donnee from france.table_liste
    LOOP
    perform 'CREATE table france.'||quote_ident(liste.nom_donnee)||'_emp AS 
SELECT nom_donnee, st_convexhull( st_collect (the_geom_wgs84))
   FROM '||quote_ident(liste.nom_donnee)||' group by nom_donnee;';
    OPEN curs FOR SELECT nom_donnee FROM table_liste;   
        FETCH curs INTO rec;
    END LOOP;
    CLOSE curs;
END;
$$ LANGUAGE plpgsql;

Et le message d'erreur qui en découle :

ERREUR:  curseur « <unnamed portal 149> » déjà en cours d'utilisation
CONTEXT:  fonction PL/pgsql fct(), ligne 12 à OPEN
********** Erreur **********

ERREUR: curseur « <unnamed portal 149> » déjà en cours d'utilisation
État SQL :42P03
Contexte : fonction PL/pgsql fct(), ligne 12 à OPEN

D'où pourrait venir le problème d'après vous?
Enfin, tout d'abord ma fonction n'est peut-être pas exact...

#8 Re : Général » Fonction permettant de créer de générer des tables » 02/06/2014 09:39:21

Bonjour,

Merci pour votre réponse!
J'avais déjà lu la doc que vous m'avez conseillé, cependant les fonction triggers, il me semble, n'effectue pas de "create table" si?
Plus simplement je voudrait créer une fonction me permettant un "create table T as select st_convexhull(the_geom)" (la syntaxe est à titre indicatif), dés l'insertion d'une nouvelle table.
Je ne sais pas si ce que je souhaite est possible, qu'en pensé vous?

Sadewizz

#9 Général » Fonction permettant de créer de générer des tables » 30/05/2014 11:51:17

Sadewizz
Réponses : 7

Bonjour,

je suis novice en ce qui concerne postgres/gis, et dans le cadre d'un stage je suis amené à créer une base donnée spatiale.
Ma question est la suivante: Une fonction plp/gsql ou autre peut elle générer automatiquement une table ?

Je m'explique. j'ai déjà une vue me permettant de lister toutes me tables de manière dynamique. Mais je voudrait qu'a l'insertion de chaque table, une fonction, ou plusieurs, me récupère le nom de la nouvelle table dans la liste en question,  et crée une autre nouvelle table de style st_convexhull à partir de cette nouvelle table en récupérant juste les informations souhaitées.
Cela est il possible ?

Merci pour vos réponses,
Sadewizz.

#10 Re : PL/pgSQL » fonction union de toutes les tables » 23/05/2014 16:33:57

Salut Géronimo,

Il me semble qu'avec "RETURN NEXT", il me signalait un erreur de syntaxe...
Mais merci pour ton intervention wink.

#11 Re : PL/pgSQL » fonction union de toutes les tables » 23/05/2014 16:31:04

Re salut,

Pour ceux que sa intéressent, j'ai pu résoudre mon problème (avec un peu de chance).

--drop function table_union();
CREATE OR REPLACE FUNCTION table_union () RETURNS table (i varchar, n varchar, g geometry)  
language plpgsql
as
$BODY$
DECLARE
 tables record;
BEGIN
  FOR tables IN SELECT tablename FROM pg_tables where tablename 
		 IN 
		(select tablename from pg_tables where schemaname ='france' and tablename in (SELECT f_table_name FROM geometry_columns where f_table_name not like '%_t' and f_table_name not like 'france_littoral' and f_table_name not like 'box%' and f_table_name not like 'rast%'))
  LOOP
  return query Execute 'select '||quote_ident (tables.tablename)||'.id , '||quote_ident(tables.tablename)||'.nom_donnee, '||quote_ident(tables.tablename)||'.the_geom_wgs84  from '||quote_ident(tables.tablename)||';' 
    RETURN ;
  END LOOP;
END
$BODY$;

Le "RETURN QUERY" a tout changé il faut croire.

Bon week end!
Sadewizz (steack de cerf! wink)

#12 PL/pgSQL » fonction union de toutes les tables » 23/05/2014 15:56:43

Sadewizz
Réponses : 5

Bonjour,

Ci dessous j'ai essayer de mettre en place une fonction me permettant de récupérer certaines infos sur mes tables en faisant une union entre elles.
seulement la fonction s'effectue mais me renvoie 0 résultat avec la requête suivante :

select * from table_union();

Mon code :

CREATE OR REPLACE FUNCTION table_union () RETURNS table(i text, n text, g geometry)  
language plpgsql
as
$BODY$
DECLARE
 tables record;
BEGIN
  FOR tables IN SELECT tablename FROM pg_tables where tablename 
		 IN 
		(select tablename from pg_tables where schemaname ='france' and tablename in (SELECT f_table_name FROM geometry_columns where f_table_name not like '%_t' and f_table_name not like 'france_littoral' and f_table_name not like 'box%' and f_table_name not like 'rast%'))
  LOOP
   Execute 'select '||quote_ident (tables.tablename)||'.id as id, '||quote_ident(tables.tablename)||'.nom_donnee as nom, '||quote_ident(tables.tablename)||'.the_geom_wgs84 as yhe_geom from '||quote_ident(tables.tablename)||';' 
    RETURN ;
  END LOOP;
END
$BODY$;

Avez vous une idée de la provenance de mon / mes erreurs?
Merci pour d'éventuelles éclaircicement et bon week end a vous!!

#13 Re : PL/pgSQL » Fonction permettant de récupérer l'id et la géométrie de mes tables » 21/05/2014 13:13:05

Salut Géronimo,

Merci pour ta réponse. Cependant le résultat obtenu avec Row_number ne me numérote que les lignes des tables dont les id ont été extraient. Comme il ne m'extrait qu'une seule ligne par table me met 1 à chaque ligne.
Enfin pour ma part il me semble que ce soit çà...
En tout cas merci pour ton aide. Je continue de chercher et apporterais une solution si toutefois j'en trouve une.
Mais si quelqu'un à deux ou trois pistes, je suis preneur wink

Bonne après midi!!

#14 PL/pgSQL » Fonction permettant de récupérer l'id et la géométrie de mes tables » 21/05/2014 10:22:59

Sadewizz
Réponses : 2

Fonction permettant de récupérer l'id et la géométrie de mes tables

Bonjour,

Je suis nouveau sur le site. J'espere pouvoir trouver un peu d'aide ici.
J'ai un petit problème avec une fonction :

CREATE OR REPLACE FUNCTION test3(OUT nom_table text, OUT id_table text, OUT table_geometry geometry ) RETURNS SETOF record
LANGUAGE plpgsql
AS
$BODY$
DECLARE
  tables record;
BEGIN
  FOR tables IN SELECT tablename FROM pg_tables where tablename 
		 IN 
		(
		(SELECT f_table_name FROM geometry_columns where f_table_name not like 'box_%' and f_table_name not like 'rast%') 
                 UNION (SELECT 'spatial_ref_sys') UNION (select f_geometry_column from geometry_columns where f_geometry_column not like 'the_geom_wgs84')
		) 
	AND pg_tables.schemaname='france'  
  LOOP
    nom_table := tables.tablename;
    EXECUTE 'SELECT id FROM '|| quote_ident(tables.tablename)
      INTO id_table;
    EXECUTE 'SELECT the_geom_wgs84 FROM ' || quote_ident(tables.tablename)
      INTO table_geometry;
    RETURN NEXT;
  END LOOP;
END
$BODY$;

Cette fonction me renvoie comme résultat, un tableau contenant le nom de ma donnée, un id pris au hasard (je suppose ?) et une ligne géométrique.
Cependant, impossible de visualiser çà dans un client carto.
Ce que je voudrais c'est pouvoir récupérer chaque ligne de mes tables en fonction de leurs id (qui est unique) et leurs coordonnées géométriques.
Tout d'abord, est ce possible ?

Merci d'avance pour d'éventuelle réponse.
S.

Pied de page des forums

Propulsé par FluxBB