web-dev-qa-db-ja.com

エラー:セットを受け入れることができないコンテキストで呼び出されたset_valued関数。どんな内容ですか?

私は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行)は明らかにタプルです。

一時テーブルを作成する必要がある/すべきですか?

11

エラーメッセージはあまり役に立ちません。

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)
7
Craig Ringer