Функция PostgreSQL, возвращающая несколько результирующих наборов - PullRequest
17 голосов
/ 16 апреля 2009

Можно ли вернуть несколько наборов результатов из функции Postgres, как в MSSQL:

CREATE PROCEDURE test

AS

SELECT * FROM first_table

SELECT * FROM second_table

Ответы [ 4 ]

13 голосов
/ 13 октября 2011

Более простой способ был около , начиная с PostgreSQL 8.3 :

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

RETURN QUERY
SELECT * FROM first_table;

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

END
$func$ LANGUAGE plpgsql;

Звоните:

SELECT * FROM test();

Оба набора результатов добавляются к одному набору, возвращенному функцией.
См. руководство по RETURN QUERY.

9 голосов
/ 16 апреля 2009
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. используя refcursors:)

1 голос
/ 16 апреля 2009

Если first_table и second_table имеют одинаковую раскладку, вы также можете просто использовать

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

[РЕДАКТИРОВАТЬ: Спасибо закомментатор (имя которого, вероятно, не "null" :)) за указание, что UNION ALL быстрее, чем UNION.]

0 голосов
/ 16 апреля 2009

Да.

Пример:

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)

Конечно, вы можете использовать существующую таблицу / представление или пользовательский тип для возвращаемого типа.

Пример использования языка 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)

Смотрите здесь документ

...