私はubuntu 12.04でPostgresql 9.1を使用しています。
私の質問へのクレイグの回答に触発されました setofタイプまたはsetofレコードの連結 _return query
_、_setof record
_、およびシリーズジェネレーターをこのplpgsql関数に使用するとうまくいくと思いました:
_create or replace function compute_all_pair_by_craig(id_obj bigint)
returns setof record as $$
begin
return query select o.id, generate_series(0,o.value) from m_obj as o;
end;
$$ language plpgsql;
_
実行中にエラーが発生します:
_ERROR: set_valued function called in context that cannot accept a set
_
なにが問題ですか ? Craigとは異なり、私は関数に_setof record
_を返すように指示します。
Craigとまったく同じように機能する何かを実現できます。つまり、型create type pair_id_value as (idx bigint, value integer)
を定義して、plpgsql関数で_setof of pair_id_value
_ではなく_setof record
_を返すようにすることができます。
しかし、この作業ソリューションを使用しても、select id, generate_series(0,13)
だけが2つの列...で結果を返す理由がわかりません。逆に、return query select id, generate_series(0,my_obj.value) from my_obj
を使用して関数を呼び出す(setof pair_id_valueを返す)と、結果は1列のみになり、フィールドは次のようになります。この「(123123,0)」「(123123,1)」「(123123,2)」(3行)は明らかにタプルです。
一時テーブルを作成する必要がある/すべきですか?
エラーメッセージはあまり役に立ちません。
regress=> SELECT * FROM compute_all_pair_by_craig(100);
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM compute_all_pair_by_craig(100);
しかし、クエリを言い換えて適切なセットを返す関数として呼び出すと、実際の問題がわかります。
regress=> SELECT * FROM compute_all_pair_by_craig(100);
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM compute_all_pair_by_craig(100);
OUT
パラメータリストなしでSETOF RECORD
を使用している場合は、呼び出しステートメントで結果を指定する必要があります。例:
regress=> SELECT * FROM compute_all_pair_by_craig(100) theresult(a integer, b integer);
ただし、RETURNS TABLE
またはOUT
パラメーターを使用する方がはるかに優れています。前者の構文では、関数は次のようになります。
create or replace function compute_all_pair_by_craig(id_obj bigint)
returns table(a integer, b integer) as $$
begin
return query select o.id, generate_series(0,o.value) from m_obj as o;
end;
$$ language plpgsql;
これはSELECTリストのコンテキストで呼び出すことができ、型を明示的に作成したり、呼び出しサイトで結果構造を指定したりせずに使用できます。
質問の後半については、最初のケースでSELECTリストの2つの個別の列が指定されているのに対して、2番目のケースでは単一のコンポジットが返されます。実際には、結果を返す方法ではなく、関数を呼び出す方法と関係があります。サンプル関数を作成すると:
CREATE OR REPLACE FUNCTION twocols() RETURNS TABLE(a integer, b integer)
AS $$ SELECT x, x FROM generate_series(1,5) x; $$ LANGUAGE sql;
セットを返す関数を呼び出す2つの方法の違いがわかります-SELECT
リストでは、風変わりな動作を持つPostgreSQL固有の非標準拡張機能です。
regress=> SELECT twocols();
twocols
---------
(1,1)
(2,2)
(3,3)
(4,4)
(5,5)
(5 rows)
またはより標準的な方法でテーブルとして:
regress=> SELECT * FROM twocols();
a | b
---+---
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
(5 rows)