4

タプル構造を同時に宣言しながら、レコードまたは行を宣言する方法を示すPostgreSQLドキュメントには何も見つかりません。タプル構造を定義しないと、「まだ割り当てられていないレコードのタプル構造が不確定です」というエラーが発生します。

これは私が今していることであり、うまく機能しますが、それを行うためのより良い方法があるはずです。

CREATE OR REPLACE FUNCTION my_func()
  RETURNS TABLE (
    "a" integer,
    "b" varchar
  ) AS $$
DECLARE r record;
BEGIN

CREATE TEMP TABLE tmp_t (
    "a" integer,
    "b" varchar
);
-- Define the tuple structure of r by SELECTing an empty row into it.
-- Is there a more straight-forward way of doing this?
SELECT * INTO r
FROM tmp_t;

-- Now I can assign values to the record.
r.a := at.something FROM "another_table" at
       WHERE at.some_id = 1;

-- A related question is - how do I return the single record 'r' from
-- this function?
-- This works:
RETURN QUERY
SELECT * FROM tmp_t;

-- But this doesn't:
RETURN r;
-- ERROR:  RETURN cannot have a parameter in function returning set

END; $$ LANGUAGE plpgsql;
4

3 に答える 3

14

値を返すための構文と、単一の行または値を返すための構文をSETOF混在させています。

-関連する質問は-単一のレコード「r」をから返すにはどうすればよいですか

RETURNS TABLEを使用して関数を宣言する場合RETURN NEXT、行(またはスカラー値)を返すために本文で使用する必要があります。recordまた、変数を使用する場合は、戻り値の型と一致する必要があります。さらに下のコード例を参照してください。

単一の値または行を返します

単一の行を返したいだけの場合は、未定義のタイプのレコードは必要ありません。@Kevinはすでに2つの方法を示しました。パラメータを使用して簡略化されたバージョンを追加しOUTます。

CREATE OR REPLACE FUNCTION my_func(OUT a integer, OUT b text)
   AS
$func$
BEGIN
   a := ...;
   b := ...;
END
$func$ LANGUAGE plpgsql;

RETURN;関数本体に追加する必要はありません。宣言されたOUTパラメーターの値は、関数の最後に自動的に返されます-NULL割り当てられていないパラメーターについては。また、パラメータからすでに明らかであるため、
宣言する必要はありません。RETURNS RECORDOUT

行のセットを返します

実際に複数の行を返したい場合(0または1行の可能性を含む)、戻りタイプをRETURNS...として定義できます。

  • SETOF some_type、ここでsome_type、登録されたスカラーまたは複合型を指定できます。

  • TABLE (col1 type1, col2 type2)-アドホックな行タイプの定義。

  • SETOF recordさらにOUT、列名とタイプを定義するためのパラメーター。
    に100%相当しRETURNS TABLEます。

  • SETOF recordそれ以上の定義なし。ただし、返される行は未定義であり、すべての呼び出しに列定義リストを含める必要があります(例を参照)。

レコードタイプに関するマニュアル

レコード変数は行型変数に似ていますが、事前定義された構造はありません。これらは、SELECTまたはFORコマンド中に割り当てられた行の実際の行構造を引き継ぎます。

もっとあります、マニュアルを読んでください。

定義されたタイプを割り当てずにレコード変数を使用できそのような未定義のレコードを返すこともできます。

CREATE OR REPLACE FUNCTION my_func()
  RETURNS SETOF record AS
$func$
DECLARE
    r record;
BEGIN
    r := (1::int, 'foo'::text); RETURN NEXT r; -- works with undefined record
    r := (2::int, 'bar'::text); RETURN NEXT r;
END
$func$ LANGUAGE plpgsql;

電話:

SELECT * FROM my_func() AS x(a int, b text);

ただし、呼び出しごとに列定義リストを提供する必要があるため、これは非常に扱いにくいです。通常、よりエレガントなものに置き換えることができます。

  • 関数作成時にタイプがわかっている場合は、すぐに(RETURNS TABLEまたは友達に)宣言してください。

CREATE OR REPLACE FUNCTION my_func()
  RETURNS SETOF tbl_or_type AS
$func$
DECLARE
    r tbl_or_type;
BEGIN
    SELECT INTO tbl_or_type  * FROM tbl WHERE id = 10;
    RETURN NEXT r;  -- type matches

    SELECT INTO tbl_or_type  * FROM tbl WHERE id = 12;
    RETURN NEXT r;

    -- Or simpler:
    RETURN QUERY
    SELECT * FROM tbl WHERE id = 14;
END
$func$ LANGUAGE plpgsql;

あなたの質問はあなたが正確に何を必要としているかについてはっきりしていません。

于 2012-08-11T04:39:54.853 に答える
4

明示的な型宣言を回避する方法があるかもしれませんが、私が思いつくことができる最善の方法は次のとおりです。

CREATE TYPE my_func_return AS (
    a integer,
    b varchar
  );

CREATE OR REPLACE FUNCTION my_func()
  RETURNS my_func_return AS $$
DECLARE
  r my_func_return;
BEGIN
  SELECT 1, 'one' INTO r.a, r.b;
  RETURN r;
END; $$ LANGUAGE plpgsql;

ああ、私はこれを行う最も簡単な方法をほとんど忘れていました:

CREATE OR REPLACE FUNCTION my_func2(out a int, out b text)
  RETURNS RECORD AS $$
BEGIN
  SELECT 1, 'one' INTO a, b;
  RETURN;
END; $$ LANGUAGE plpgsql;
于 2012-08-10T19:42:55.023 に答える
1

OUTレコードよりもパラメータを使用する方がはるかに簡単です。レコードのセット(テーブル)を繰り返し作成する場合は、を使用しますRETURN NEXT。クエリから生成する場合は、を使用しますRETURN QUERY。見る:

https://stackoverflow.com/a/955289/398670

と:

http://www.postgresql.org/docs/current/static/plpgsql-declarations.html http://www.postgresql.org/docs/current/static/sql-createfunction.html http://www.postgresonline。 com / journal / archives /129-Use-of-OUT-and-INOUT-Parameters.html

考え:

CREATE OR REPLACE FUNCTION my_func(OUT a integer, OUT b varchar) RETURNS SETOF RECORD AS $$
BEGIN
    -- Assign a and b, RETURN NEXT, repeat. when done, RETURN.
END;
$$ LANGUAGE 'plpgsql';  
于 2012-08-11T09:57:41.223 に答える