plpgsql returning resultset
Hi
I know the subject has been discussed before, but I dont find what any
information that helps me make it work, so please bear with me.
In pg 8.2 I want to write a function that gathers data from different
tables and joins it into a single resultset, similar to "select * from
tableA", but the problem I keep having is that I cant get the return to
work. I have tried return next and it fails. I have also tried refcursor,
but am not sure if that is the best way, its a littlebit cumbersome in a
program.
Are those the only two options? and what did I do wrong in the return next
create function test2() returns setof record as
$$
declare
val_list record;
begin
select * into val_list from tableA;
return next val_list;
return:
end
$$ .....
with the query:
select test2();
ERROR: set-valued function called in context that cannot accept a set
CONTEXT: line 9 at return next
regards thomas
On 02/09/2008 11:12, tfinneid@student.matnat.uio.no wrote:
create function test2() returns setof record as
$$
declare
val_list record;
begin
select * into val_list from tableA;
return next val_list;
return:
end
$$ .....
Hi there,
You need to do it like this:
with val_list in
select * from tableA do
loop
return next val_list;
end loop;
return;
There's an example here:
Ray.
------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------
Hi there,
You need to do it like this:
with val_list in
select * from tableA do
loop
return next val_list;
end loop;
return;There's an example here:
Does that work in 8.2, cause i get the same error message as I described
above
regards
thomas
On 02/09/2008 12:18, tfinneid@student.matnat.uio.no wrote:
Does that work in 8.2, cause i get the same error message as I described
above
Yep, it does..... I should have mentioned that you call your function
like this:
select * from my_function()
- in other words, a SETOF-returning function takes the place of a table
in a SELECT statement.
Can you show us more of your code?
Ray.
------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------
Raymond O'Donnell wrote:
Can you show us more of your code?
I figured out how to make it work when using "for" instead of "with".
Here is the code and the error message. I couldnt find anything in the
documentation about "with" but I did find something about "for" which I
managed to make work. In any case here is the code for the "with" code:
create or replace function get_profile() returns setof tableA as
$$
declare
val_list tableA%rowtype;
begin
with val_list in
select * from tableA
do
loop
return next val_list;
end loop;
return;
end;
$$ language 'plpgsql';
the error message is:
psql:functions.sql:116: ERROR: syntax error at or near "with $1"
LINE 1: with $1 in select * from attribute_values_part_seq_1_ff_5 ...
^
QUERY: with $1 in select * from attribute_values_part_seq_1_ff_5 do
loop return next $1
CONTEXT: SQL statement in PL/PgSQL function "get_profile" near line 10
Hi again, I tried to take the "with" form of the function further to
complete the actual method and met with another error message which I
dont understand.
I have a number for tables (partitioned) from which I need to retrieve
data. Another table keeps track of which tables I should read from.
The tables are named table_X, where X is 1-N. from that I want to
retrieve some data from the selected tables and add it all into one
resultset which I return to the client.
The code is as follows:
create function get_profile(se_arg int4, st_arg int4, tr_arg int4)
returns setof table_part as
$$
declare
table_name text;
val_list table_part%rowtype;
num_list table_part_num_list%rowtype;
begin
for num_list in select num
from table_part_num_list
where se=se_arg
loop
table_name := 'table_part_'|| num_list.num;
select * into val_list
from table_name
where st=st_arg and tr=tr_arg;
return next val_list;
end loop;
return;
end;
$$ language 'plpgsql';
the error message I get when I try to create the function is:
psql:functions.sql:159: ERROR: syntax error at or near "$1"
LINE 1: select * from $1 where st= $2 and tr= $3
^
QUERY: select * from $1 where st= $2 and tr= $3
CONTEXT: SQL statement in PL/PgSQL function "get_profile" near line 15
Any ideas what I am doing wrong?
regards
thomas
On 02/09/2008 21:55, Thomas Finneid wrote:
with val_list in
select * from tableA
do
loop
return next val_list;
end loop;
Oops - my mistake - it should indeed be FOR, not WITH, hence your error
message.
One other thing in the above - you don't need the DO, it's just
FOR...LOOP...END LOOP.
Ray.
------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------
PostgreSQL has table partitioning in it so you don't have to dynamically
figure out which table to get the data from.
http://www.postgresql.org/docs/8.3/interactive/ddl-partitioning.html
However, you can achieve dynamic SQL in plpgsql too.
http://www.postgresql.org/docs/8.3/interactive/ecpg-dynamic.html
Jon
-----Original Message-----
From: pgsql-general-owner@postgresql.org [mailto:pgsql-general-
owner@postgresql.org] On Behalf Of Thomas Finneid
Sent: Tuesday, September 02, 2008 4:19 PM
To: pgsql-general@postgresql.org
Cc: rod@iol.ie
Subject: Re: [GENERAL] plpgsql returning resultsetHi again, I tried to take the "with" form of the function further to
complete the actual method and met with another error message which I
dont understand.I have a number for tables (partitioned) from which I need to retrieve
data. Another table keeps track of which tables I should read from.
The tables are named table_X, where X is 1-N. from that I want to
retrieve some data from the selected tables and add it all into one
resultset which I return to the client.The code is as follows:
create function get_profile(se_arg int4, st_arg int4, tr_arg int4)
returns setof table_part as
$$
declare
table_name text;
val_list table_part%rowtype;
num_list table_part_num_list%rowtype;
beginfor num_list in select num
from table_part_num_list
where se=se_arg
loop
table_name := 'table_part_'|| num_list.num;select * into val_list
from table_name
where st=st_arg and tr=tr_arg;return next val_list;
end loop;return;
end;
$$ language 'plpgsql';the error message I get when I try to create the function is:
psql:functions.sql:159: ERROR: syntax error at or near "$1"
LINE 1: select * from $1 where st= $2 and tr= $3
^
QUERY: select * from $1 where st= $2 and tr= $3
CONTEXT: SQL statement in PL/PgSQL function "get_profile" near line
15
Show quoted text
Any ideas what I am doing wrong?
regards
thomas
--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general
I believe you need to use for execute '...' loop, since
the table_name is dynamically composed.
Regards,
Alex Vinogradovs
Show quoted text
On Tue, 2008-09-02 at 23:19 +0200, Thomas Finneid wrote:
Hi again, I tried to take the "with" form of the function further to
complete the actual method and met with another error message which I
dont understand.I have a number for tables (partitioned) from which I need to retrieve
data. Another table keeps track of which tables I should read from.
The tables are named table_X, where X is 1-N. from that I want to
retrieve some data from the selected tables and add it all into one
resultset which I return to the client.The code is as follows:
create function get_profile(se_arg int4, st_arg int4, tr_arg int4)
returns setof table_part as
$$
declare
table_name text;
val_list table_part%rowtype;
num_list table_part_num_list%rowtype;
beginfor num_list in select num
from table_part_num_list
where se=se_arg
loop
table_name := 'table_part_'|| num_list.num;select * into val_list
from table_name
where st=st_arg and tr=tr_arg;return next val_list;
end loop;return;
end;
$$ language 'plpgsql';the error message I get when I try to create the function is:
psql:functions.sql:159: ERROR: syntax error at or near "$1"
LINE 1: select * from $1 where st= $2 and tr= $3
^
QUERY: select * from $1 where st= $2 and tr= $3
CONTEXT: SQL statement in PL/PgSQL function "get_profile" near line 15Any ideas what I am doing wrong?
regards
thomas
On 02/09/2008 22:19, Thomas Finneid wrote:
for num_list in select num
from table_part_num_list
where se=se_arg
loop
table_name := 'table_part_'|| num_list.num;select * into val_list
from table_name
where st=st_arg and tr=tr_arg;return next val_list;
I think you need to build the query dynamically as a string, then
execute it using EXECUTE:
http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
So something like this (I haven't tried it):
loop
execute 'select * into val_list from '
|| 'table_part_' || num_list.num
|| ' where st = st_arg and tr = tr_arg';
return next val_list;
end loop;
Hopefully this will work.
Ray.
------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------
Roberts, Jon wrote:
PostgreSQL has table partitioning in it so you don't have to dynamically
figure out which table to get the data from.
I know, but the super table can't handle the number of partition tables
I need, 10K-100K tables. Whenever I do a query on the super table, it
just aborts.
regards
thomas