サニタイズ機能
現在お持ちのものは、次のように簡略化/サニタイズできます:
CREATE OR REPLACE FUNCTION func_a (username text = '', databaseobject text = '')
RETURNS ????
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
BEGIN ... END
の追加インスタンスのみが必要です 関数本体で、独自のスコープで個別のコードブロックを開始します。これは、ほとんど必要ありません。
標準のSQL連結演算子は||
です。 。 +
以前のベンダーの「創造的な」追加です。
キャメルケースの識別子は、二重引用符で囲まない限り使用しないでください。まったく使用しないでください。参照:
- PostgreSQLの列名では大文字と小文字が区別されますか?
varchar(4000)
また、SQLServerの特定の制限に合わせて調整されています。 Postgresでは特に重要ではありません。 varchar(4000)
のみを使用してください 実際に4000文字の制限が必要な場合。 text
を使用します -変数がまったく必要ないことを除いて ここでは、関数を単純化した後。
format()
を使用したことがない場合 、まだ、ここのマニュアルを参照してください。
リターンタイプ
さて、実際の質問です。SQLでは遅くとも呼び出し時に宣言する必要があるため、動的クエリの戻り型は扱いにくい場合があります。データベースにすでに列定義リストと一致するテーブル、ビュー、または複合型がある場合は、次のように使用できます。
CREATE FUNCTION foo()
RETURNS SETOF my_view AS
...
それ以外の場合は、(最も単純な)RETURNS TABLE
を使用せずに列定義リストをスペルします。 :
CREATE FUNCTION foo()
RETURNS TABLE (col1 int, col2 text, ...) AS
...
行の種類を増やしていく場合は、匿名のレコードを返すことができます:
CREATE FUNCTION foo()
RETURNS SETOF record AS
...
ただし、呼び出しごとに列定義リストを提供する必要があるため、これを使用することはほとんどありません。
SELECT *
は使用しません そもそも。列の明確なリストを使用して、戻り値を返し、それに応じて戻り値のタイプを宣言します。
CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
RETURNS TABLE(col1 int, col2 text, col3 date)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ($f$SELECT v1.col1, v1.col2, v2.col3
FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
完全に動的なクエリの場合は、関数を使用するのではなく、最初にクライアントでクエリを作成することを検討してください。
最初に基本を理解する必要があります:
- PL / pgSQL関数をリファクタリングして、さまざまなSELECTクエリの出力を返します
- PostgresマニュアルのPL/pgSQL
次に、ポリモーフィックタイプを使用したより高度なオプションがあります。これにより、呼び出し時にリターンタイプを渡すことができます。詳細については、次の章をご覧ください:
- PL / pgSQL関数をリファクタリングして、さまざまなSELECTクエリの出力を返します