web-dev-qa-db-ja.com

SELECTリストのSet Returning Function(SRF)について

SELECTリストでSet Returning Function(SRF)を使用する場合とFROM句でSRFを使用する場合の動作に違いがあるのはなぜですか?

たとえば、2つの行を返す単純なSRFの場合:

_CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
  RETURNS SETOF record AS $$
  SELECT 1,1
  UNION
  SELECT 2,2;
$$ LANGUAGE SQL;
_

SELECT gen_series();は、それぞれレコードを含む2つの単一列行を返します。

_=>  gen_series 
------------
 (1,1)
 (2,2)
(2 rows)
_

一方、SELECT * FROM gen_series();は、レコードが展開された2つの行を返します。

_=>  column1 | column2 
---------+---------
       1 |       1
       2 |       2
(2 rows)
_

比較すると、SRFが単一の列を返す場合、SELECTまたはFROM句でSRFを呼び出しても違いはありません。例えば。:

_=> SELECT generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)

=> SELECT * FROM generate_series(1,2);
 generate_series 
-----------------
               1
               2
(2 rows)
_

私の質問は:

  1. 2番目のケースでは、返されたテーブルに単一の列があるという理由だけで、SRFの動作が最初のケースと異なる理由がよくわかりません。これは、型、タプル、およびセットに関して、本当に一貫した動作ですか?

  2. 異なる動作につながる2つのケースの違いは何ですか?

  3. 上記のようにSRFをテーブルとして使用できますが、テーブルを使用してSRFを置き換えることもできますか?例えば.

    _SELECT my_table; 
    _

どうやら、これは実行できませんが、_SELECT my_table;_が(関係と数学の観点から)許可されていないのに、なぜSELECT my_SRF();が可能なのですか?

8
tinlyx

Postgresは単純なケースを別の方法で扱います。複数の列は_SELECT * FROM ..._でのみ分解される複合型(テーブル行)として扱われますが、スカラー型の単一の列はそのように扱われ、複合型ラッパーは追加されません。したがって、SELECT my_SRF()は、単純な場合のSELECT * FROM my_SRF()と同じ結果を生成します。 テーブル関数に関するマニュアル

テーブル関数は、基本データ型(スカラー型)または複合データ型(テーブル行)で構成される行のセットを生成する関数です。

私はこれが混乱することに同意します、そしてあなたは混乱する最初のものではありません。 (ただし、別の方法を検討してください。単一の列の周りに複合型ラッパーを追加すると、さらに混乱する可能性があります。)

ただし、SELECTリストでmultipleSRF関数を組み合わせたときに何が起こるかほど複雑ではありません。ただし、これはPostgres 10で完全に変更される予定です。

どちらの場合も安全で混乱の少ない方法は、SRF関数をFROM句に移動することです。別のテーブルの列を参照する必要がある場合は、LATERAL結合を使用します。 マニュアルは次のことを示唆しています:

LATERAL構文は、複数のセットを返す関数を呼び出すときにそれほど驚くべき結果を生成しないため、通常は代わりに使用する必要があります。

3