web-dev-qa-db-ja.com

引数が(サブ)選択ステートメントである関数の呼び出し

私の関数はint4を引数として、テーブルを返します。

SELECT * FROM test_function(545421); -- works fine

SELECT * FROM test_function(SELECT customerid
                            FROM tableX where id = 1); -- syntax error

どうすればこれを機能させることができますか?
サーバーPostgreSQL 9.3.1

7
Beig

1.サブクエリ式

@ a_horse のような括弧でそれを修正することができます:

SELECT * FROM test_function((SELECT customerid FROM tableX where id = 1));

しかし、このフォームはかなりエラーが発生しやすくなります。コードには、副選択が単一の行のみを返すことを保証するものはありません。 idが一意であるかどうか、またPostgresも一意であるかどうかはわかりません(システムカタログを検索しない限り)。私たちはそれに依存する必要があり、壊れないことを願っています。

確かにLIMIT 1を追加することもできますが、決定的な結果を得るためにORDER BYも追加する必要があります...

2. JOIN LATERAL

この(Postgres9.3+)の最新の構文は、LATERAL結合になります。

SELECT f.* 
FROM   tableX t, test_function(t.customerid) f
WHERE  t.id = 1;

これは短い構文です:

SELECT f.* 
FROM   tableX t
CROSS  JOIN LATERAL test_function(t.customerid) f
WHERE  t.id = 1;

上記とまったく同じ結果ですが、1つ微妙ですが重要な違いがある可能性があります

    1. tableXt.id = 1の行が行がない場合、関数は呼び出されず、クエリは何も返しません(行なし)。一方、customerid IS NULLで行が見つかった場合、関数はNULL入力で呼び出され、関数がNULLに対して返すものをすべて取得します。
      それはあるべき姿です。
    1. サブクエリ式を含むフォームでは、これら2つのケースを区別できません。 「行なし」は、customeridNULLであることと同じNULL値になります。関数は、どちらの方法でもNULL入力で呼び出されます。
      それはではありませんどうあるべきか。

LATERALクエリは、idが一意でない場合でもブレークしません。また、必要に応じて、tableXから追加の列を簡単に返すことができます。

13