tags:

views:

1216

answers:

3

Hi! Is it possible to return multiple result sets from a Postgres function, like in MSSQL:

` CREATE PROCEDURE test

AS

SELECT * FROM first_table

SELECT * FROM second_table `

+1  A: 

Yes.

Example:

test=# create function x () returns setof integer language plpgsql as $$ begin return next 1; return next 2; end $$;
CREATE FUNCTION
test=# select * from x();
 x 
---
 1
 2
(2 rows)

You can of course use an existing table/view or a custom type for the returned type.

Example using language SQL:

test=# create table customer (name varchar, birth_date date);
CREATE TABLE
test=# create function y () returns setof customer language sql as $$ 
select * from customer
union all
select * from customer
$$;
CREATE FUNCTION
test=# insert into customer values ('joe', now()::date);
INSERT 0 1
test=# insert into customer values ('jill', now()::date);
INSERT 0 1
test=# select * from y();
 name | birth_date 
------+------------
 joe  | 2009-04-16
 jill | 2009-04-16
 joe  | 2009-04-16
 jill | 2009-04-16
(4 rows)

See here for doc

+1  A: 
CREATE OR REPLACE FUNCTION "pr_GetCustomersAndOrders"()
RETURNS SETOF refcursor AS
$BODY$DECLARE
customerRC refcursor;
orderRC refcursor;
BEGIN
open customerRC FOR
SELECT * FROM customers;
RETURN NEXT customerRC;

open orderRC FOR
SELECT * FROM orders;
RETURN NEXT orderRC;
RETURN;
END;$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION "pr_GetCustomersAndOrders"() OWNER TO postgres;

I.o.w. using refcursors :)

Frans Bouma
+1  A: 

If first_table and second_table have the same layout, you can also just use

SELECT * FROM first_table WHERE ...
UNION ALL
SELECT * FROM second_table WHERE ...

[EDIT: Thanks to a commenter (whose name is probably not "null" :) ) for pointing out that UNION ALL is faster than UNION.]

j_random_hacker
Nitpicking, but UNION ALL would be quicker (there is no "| sort | uniq"), but will return duplicates if there are any.
@null: Good point; updated. (I realise your name probably isn't "null" -- seems a recent SO bug causes this. I was able to fix it by editing the top field on my profile page.)
j_random_hacker
Yes but what about queries that don't return the same layouts ? It quite limitative if we need to get many sets. I use to have Stored Procedure in SQL Server which returns 10+ result sets. Anything like that in PostgreSQL ?
MaxiWheat
@MaxiWheat: Frans Bouma's answer (returning REFCURSORs) covers that case, provided you remain within plpgsql. http://www.postgresql.org/docs/8.4/interactive/plpgsql-cursors.html explains how cursors can be passed back outside of plpgsql (e.g. to be used with a client library).
j_random_hacker