web-dev-qa-db-ja.com

SQL関数の戻り値の型:TABLEとSETOFレコード

TABLEを返す関数とSETOF recordsを返す関数の違いは何ですか、それ以外はすべて同じです。

CREATE FUNCTION events_by_type_1(text) RETURNS TABLE(id bigint, name text) AS $$
    SELECT id, name FROM events WHERE type = $1;
$$ LANGUAGE SQL STABLE;

CREATE FUNCTION events_by_type_2(text) RETURNS SETOF record AS $$
    SELECT id, name FROM events WHERE type = $1;
$$ LANGUAGE SQL STABLE;

これらの関数は同じ結果を返すようです。これを参照してください SQLFiddle

24
ma11hew28

SETOF recordを返す場合、出力列は型指定も名前も付けられません。したがって、このフォームは、サブクエリまたはテーブルであるかのように、FROM句で直接使用することはできません。

つまり、発行するとき:

SELECT * from events_by_type_2('social');

このエラーが発生します:

エラー:「レコード」を返す関数には列定義リストが必要です

ただし、SQL呼び出し元は、正しい列タイプに「キャスト」できます。このフォームは機能します:

SELECT * from events_by_type_2('social') as (id bigint, name text);

結果は次のようになります。

 id |名前
 ---- + ---------------- 
 1 |ダンスパーティー
 2 |ハッピーアワー
 ... 

このため、SETOF recordは実用性が低いと見なされます。結果の列タイプが事前にわからない場合にのみ使用してください。

19
Daniel Vérité

この答えは、代替のcontext where[〜#〜] table [〜#〜]and[〜#〜] setof [〜#〜]は同等です

@a_horse_with_no_nameが指摘したように、これはRETURNS SETOF "unknown record"ではなく、定義されたものです。


この例では、タイプtablesetofは同等です。

CREATE TYPE footype AS (score int, term text);

CREATE FUNCTION foo() RETURNS SETOF footype AS $$
   SELECT * FROM ( VALUES (1,'hello!'), (2,'Bye') ) t;
$$ language SQL immutable;

CREATE FUNCTION foo_tab() RETURNS TABLE (score int, term text) AS $$
   SELECT * FROM ( VALUES (1,'hello!'), (2,'Bye') ) t;
$$ language SQL immutable;

SELECT * FROM foo();      -- works fine!
SELECT * FROM foo_tab();  -- works fine and is equivalent.

RETURNS SETOFには再利用タイプの利点があります(footype)、それはRETURNS TABLEでは不可能です。

10
Peter Krauss