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
`
share|improve this question
feedback

4 Answers

A simpler way has been around since PostgreSQL 8.3 (long before this question was asked!):

CREATE FUNCTION test()
RETURNS SETOF first_table
AS $$
BEGIN

RETURN QUERY
SELECT * FROM first_table;

RETURN QUERY
SELECT * FROM second_table;   -- has to return same rowtype as first_table!

END;
$$  language plpgsql;

Call:

SELECT * FROM test();

See the manual on RETURN QUERY.

share|improve this answer
feedback

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.]

share|improve this answer
1  
Nitpicking, but UNION ALL would be quicker (there is no "| sort | uniq"), but will return duplicates if there are any. – tommym Apr 16 '09 at 15:47
@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 Apr 16 '09 at 17:37
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 Oct 2 '09 at 20:16
@MaxiWheat: Frans Bouma's answer (returning REFCURSORs) covers that case, provided you remain within plpgsql. 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 Oct 3 '09 at 14:11
feedback

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

share|improve this answer
feedback
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 :)

share|improve this answer
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.