SELECTリストのセットリターン関数(SRF)について


8

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_SRF();可能である のに、SELECT my_table;(関係と数学の観点から)許可されていないのですか?


SELECT my_table;有効な構文ではありません
ムラデンUzelac

回答:


3

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

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.