18

テーブルを返す plpgsql 関数が PostgreSQL 9.2 にあります。関数は、関数と同じ列を返すいくつかの SELECT を実行し、いくつかのチェックに応じて、それらの結果を返すか、例外を発生させます。これを行う唯一の方法は FOR ... LOOP を使用することですが、行を返す便利な方法がわかりません。

私はこのようなことをしたい:

CREATE OR REPLACE FUNCTION my_function()
RETURNS TABLE(column1 integer, column2 boolean, ...)
AS $BODY$
DECLARE
    result_row RECORD;
BEGIN
    FOR result_row IN (SELECT * FROM other_function_returning_same_columns()) LOOP
        IF something_wrong_with(result_row) THEN
            RAISE EXCEPTION 'Something went wrong';
        END IF;

        RETURN NEXT result_row;
    END LOOP;
END
$BODY$ LANGUAGE plpgsql STABLE;

これは私にエラーを与えます:

エラー: RETURN NEXT は、OUT パラメータを持つ関数にパラメータを持つことはできません

関数が SETOF ではなく TABLE を返すことを除いて、私のコードはドキュメンテーションの例とよく似ているため、なぜ Postgres がここで不平を言っているのかわかりません。OUT パラメータはありません。

私は最終的にそれを使用して動作させることができました

RETURN QUERY SELECT result_row.column1, result_row.column2, ...;

しかし、常にすべての列をリストしなければならないのは見苦しく、維持するのが困難です。きっともっと良い方法があるはずです。

4

1 に答える 1

27

RETURN NEXT現在保持している出力パラメータを返すだけです。マニュアル

出力パラメーターを使用して関数を宣言した場合は、RETURN NEXT式なしで記述してください。

あなたは反対します:

OUTパラメータはありません。

出力パラメーターは、キーワードOUTorを使用して関数パラメーター間で宣言するINOUT、句で暗黙的に宣言します。RETURNS

RETURNS TABLE(column1 integer, column2 boolean, ...)

ここにcolumn1column2OUTパラメータがあります。

これはそれを行う必要があります:

CREATE OR REPLACE FUNCTION my_function()
  RETURNS TABLE(column1 integer, column2 boolean, ...)
  LANGUAGE plpgsql STABLE AS
$func$
BEGIN
   FOR column1, column2, ... IN 
      SELECT * FROM other_function_returning_same_columns()
   LOOP
      IF something_wrong_with(column1, column2, ...) THEN
         RAISE EXCEPTION 'Something went wrong';
      END IF;

      RETURN NEXT;
   END LOOP;
END
$func$;

登録されたタイプでよりシンプル

登録された複合型を使用すると、さらに単純化できます。

CREATE TYPE mytype (column1 integer, column2 boolean, ...);

または、タイプがテーブル定義と一致する場合は、すべてのテーブル名をPostgreSQLのタイプ名として使用できるため、すでにそのタイプがあります。次に、単純化します。

CREATE OR REPLACE FUNCTION my_function()
  RETURNS SETOF mytype
  LANGUAGE plpgsql STABLE AS
$func$
DECLARE
   _r mytype;
BEGIN
   FOR _r IN 
     SELECT * FROM other_function_returning_same_columns()
   LOOP
      IF something_wrong_with(_r) THEN
         RAISE EXCEPTION 'Something went wrong';
      END IF;

      RETURN NEXT _r;
   END LOOP;
END
$func$;

再編成!

RAISEコマンドをヘルパー関数に統合しsomething_wrong_with()、ロジックを反転して、より便利な名前を付けると、次の単純なクエリにeverything_groovy()完全に置き換えることができます。my_function()

SELECT *
FROM   other_function_returning_same_columns() f
WHERE  everything_groovy(f);

または、RAISEを基本関数other_function_returning_same_columns()に統合して、さらに単純化(および高速化)します。特定の状況でのみ必要な場合RAISE EXCEPTIONは、いつでもパラメーター(デフォルト)を追加してオン/オフを切り替えることができます。

于 2012-12-26T11:19:54.123 に答える