Re: FOR-LOOP durch eine Ergebnismenge

Lists: pgsql-de-allgemein
From: Martin Spott <Martin(dot)Spott(at)mgras(dot)net>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: FOR-LOOP durch eine Ergebnismenge
Date: 2013-03-29 17:47:36
Message-ID: kj4k3m$r85ckj4k3m$r85c$1@osprey.mgras.de@osprey.mgras.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-de-allgemein

Moin zusammen,

das Verfahren ist in etlichen Quellen zu Genuege beschrieben und im
Grunde auch nicht mehr brandneu, trotzdem steh' ich mit einer ganz
simplen Angelegenheit irgendwie sehr daemlich auf der Leitung.
Vielleicht mag jemand so freundlich sein und mir weiterhelfen.

Ich habe da eine View, aus der allerlei nette Tabellen-Namen
aufgelistet werden koennen - den Inhalt kann man sich exemplarisch so
angucken:

landcover=> SELECT * FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand';
f_table_catalog | f_table_schema | f_table_name | f_geometry_column | coord_dimension | srid | type
-----------------+----------------+--------------+-------------------+-----------------+------+---------
landcover | public | clc06_sand | wkb_geometry | 2 | 4326 | POLYGON
(1 Zeile)

Natuerlich gibt es noch ein paar mehr Tabellen und auf etliche davon
will ich das gleiche Verfahren anwenden (ein SELECT * INTO ...., ich
erwarte also gar keine Ausgabe). Zum Test, ob das auch klappt, habe
ich eine kleine Funktion, die mir beweisen soll, dass der LOOP
funktioniert:

CREATE OR REPLACE FUNCTION testproc()
RETURNS void
AS $$
DECLARE
layer record;
BEGIN
FOR layer IN SELECT f_table_name FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'
LOOP
SELECT * FROM layer;
END LOOP;
END;
$$
LANGUAGE 'plpgsql';

Leider funktioniert der Beweis nicht:

landcover=> SELECT testproc();
ERROR: relation "layer" does not exist
ZEILE 1: SELECT * FROM layer

Bedeutet das, dass ich in dem LOOP den Inhalt des Iterators aus dem FOR
nicht einfach als Tabellen-Namen weiterverwenden darf ?

Besten Dank fuer Erleuchtung,
Martin.
--
Unix _IS_ user friendly - it's just selective about who its friends are !
--------------------------------------------------------------------------


From: Andreas Kretschmer <akretschmer(at)spamfence(dot)net>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: Re: FOR-LOOP durch eine Ergebnismenge
Date: 2013-03-29 18:05:32
Message-ID: 20130329180532.GA12257@tux
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-de-allgemein

Martin Spott <Martin(dot)Spott(at)mgras(dot)net> wrote:

>
> CREATE OR REPLACE FUNCTION testproc()
> RETURNS void
> AS $$
> DECLARE
> layer record;
> BEGIN
> FOR layer IN SELECT f_table_name FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'
> LOOP
> SELECT * FROM layer;

Dat geht so ned !

Du hast da nun eine Variable namens layer, diese enthält einen TEXT.
Damit frickelst Dir nun einen größeren TEXT zusammen und machts ein
EXECUTE:

execute 'select * from ' || layer || ';';

*untested*

Siehe Doku unter dynamisches SQL

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°


From: Martin Spott <Martin(dot)Spott(at)mgras(dot)net>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: Re: FOR-LOOP durch eine Ergebnismenge
Date: 2013-03-29 20:35:52
Message-ID: kj4tv6$p036kj4tv6$p036$1@osprey.mgras.de@osprey.mgras.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-de-allgemein

Andreas Kretschmer wrote:

> execute 'select * from ' || layer || ';';
>
> *untested*

.... aber schon nah dran ! ;-)
Wenn ich im FOR nur die gesuchte Spalte selektiere, wie beschrieben
als:

FOR layer IN SELECT f_table_name FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'

dann kriege ich mit dem obigen EXECUTE beim Aufruf der Funktion den
Fehler:

psql:testproc.sql:18: ERROR: syntax error at or near ")"
ZEILE 1: SELECT * FROM (clc06_sand);

Wenn ich aber den kompletten Record aus der View selektiere:

FOR layer IN SELECT * FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'

dann kann ich im EXECUTE mittels "layer.f_table_name" (anstelle nur von
"layer") wie gewuenscht damit operieren. Leider muss ich mir letztlich
doch was anderes ueberlegen, denn bei:

EXECUTE 'SELECT * INTO test FROM ' || layer.f_table_name || ';';

kriege ich letztlich:

psql:testproc.sql:18: ERROR: EXECUTE of SELECT ... INTO is not implemented
TIP: You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.

Dennoch vielen Dank fuer den zielfuehrenden Hinweis, der Versuch mit

EXECUTE 'CREATE TABLE test AS SELECT * FROM ' || layer.f_table_name || ';';

fuehrte letztlich zum gewuenschten Ergebnis !

Martin.
--
Unix _IS_ user friendly - it's just selective about who its friends are !
--------------------------------------------------------------------------


From: Andreas Kretschmer <akretschmer(at)spamfence(dot)net>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: Re: FOR-LOOP durch eine Ergebnismenge
Date: 2013-03-30 07:36:46
Message-ID: 20130330073645.GA8964@tux
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: Postg사설 토토SQL : Postg사설

Martin Spott <Martin(dot)Spott(at)mgras(dot)net> wrote:

> Andreas Kretschmer wrote:
>
> > execute 'select * from ' || layer || ';';
> >
> > *untested*
>
> .... aber schon nah dran ! ;-)

dachte ich mir schon, daß es Probleme geben wird, weil Du da mit eine
Record hantierst.

> Wenn ich im FOR nur die gesuchte Spalte selektiere, wie beschrieben
> als:
>
> FOR layer IN SELECT f_table_name FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'
>
> dann kriege ich mit dem obigen EXECUTE beim Aufruf der Funktion den
> Fehler:
>
> psql:testproc.sql:18: ERROR: syntax error at or near ")"
> ZEILE 1: SELECT * FROM (clc06_sand);
>
>
> Wenn ich aber den kompletten Record aus der View selektiere:
>
> FOR layer IN SELECT * FROM geometry_columns WHERE f_table_name LIKE 'clc06_sand'

Alternativ: die Variable als TEXT definieren und nur die Spalte
selektieren. untested, aber sollte so gehen. Ist IMHO dann sauberer,
denn stell Dir vor, da wären noch eine 2 GB große BYTEA-Spalte mit dabei
...

>
>
> Dennoch vielen Dank fuer den zielfuehrenden Hinweis, der Versuch mit

schon okay, kein Ding.

Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°


From: Martin Spott <Martin(dot)Spott(at)mgras(dot)net>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: Re: FOR-LOOP durch eine Ergebnismenge
Date: 2014-09-25 14:55:52
Message-ID: m01admk2em01adm$8k2e$1@osprey.mgras.de@osprey.mgras.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-de-allgemein

Tach zusammen,

der Vollstaendigkeit halber will ich gerne mitteilen, dass es ein
Ergebnis gibt. Ich habe das aufgrund von Zeitmangel sehr lange vor mir
hergeschoben - und weil ich annahm, dass es ausgesprochen kompliziert
wuerde. Letztlich wurde es das aber gar nicht - hier ist der
"produktive Prototyp":

http://mapserver.flightgear.org/git/gitweb.pl?p=sceneryweb;a=blob;f=SQL/fn_CSMerge.sql

Das Ganze dient dazu, in einem recht groben Basis-Datensatz von
Bodennutzungsdaten mit weltweiter Abdeckung dort genauere Daten
einzusetzen, wo es welche gibt. Im Ergebnis sieht das auf einer
Web-Map dann ungefaehr so aus - im Sueden der USA ist schon ein Band
mit neuen Daten eingepflanzt:

http://mapserver.flightgear.org/map/?lon=-99.93544&lat=34.62565&zoom=6

Tschuess,
Martin.
--
Unix _IS_ user friendly - it's just selective about who its friends are !
--------------------------------------------------------------------------