2

3 つのパラメーターを返す関数があり、そのうちの 1 つは複合型です。

CREATE OR REPLACE FUNCTION f1(
  p_text text,
  OUT result_status_id smallint,
  OUT result_status_msg text,
  OUT result_my_type my_type
  )
  RETURNS record AS
$BODY$
--body here
$BODY$
LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER
  COST 100

複合型 my_type は次のようになります。

CREATE TYPE my_type AS
   (d_real real,
    d_int1 integer,
    d_int2 integer,
    d_int3 integer,
    d_int4 integer,
    d_int5 integer,
    d_int6 integer,
    d_int7 integer,
    d_int8 integer,
    d_int9 integer,
    d_int10 integer,
    d_bool boolean,
    d_date date,
    d_text text
);

本体で関数 f1 を呼び出す別の関数 f2 があります。

CREATE OR REPLACE FUNCTION f2(
    p_text text
)
  RETURNS record AS
$BODY$
DECLARE
    l_status_id smallint;
    l_status_msg text;
    l_my_type my_type;
BEGIN
--some logic here

--this statement fails
  SELECT * FROM f1(p_text) 'x' 
  INTO l_status_id, l_status_msg, l_my_type;

--logic continues here
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER
  COST 100;

問題は、関数を使用して sql を実行すると、次のエラーが表示されることです。

ERROR: "l_my_type" is not a scalar variable

別の関数から複合型オブジェクトを取得するにはどうすればよいですか?

4

4 に答える 4

2

あなたは規則に違反しています。マニュアル:

targetは、レコード変数、行変数、または単純な変数とレコード/行フィールドのカンマ区切りのリストにすることができます。

レコードまたは行変数を複数項目リストの一部にすることはできません。 これを回避する1つの方法:INTO

CREATE OR REPLACE FUNCTION f2(p_text text)
  RETURNS record AS
$BODY$
DECLARE
   r            record;
   l_status_id  smallint;
   l_status_msg text;
   l_my_type    my_type;
BEGIN
   SELECT *
   FROM f1(p_text) x  -- don't single quote 'x'
   INTO r;

   l_status_id  := r.result_status_id;
   l_status_msg := r.result_status_msg;
   l_my_type    := r.result_my_type;

  RETURN r; -- or whatever ..
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

もっと方法があります。これでどこに行くかによって異なります。匿名のレコードを返すことはほとんどありません。

于 2012-08-31T13:56:38.697 に答える
1

タプルの複合型は、部分的にサポートされているものの 1 つであり、奇妙な問題に遭遇します (特に、ストレージのようなシンで発生しますが、それはまた別の話です)。これを実現する 1 つの方法は次のとおりです。

CREATE TYPE return_type_for_function AS (
       result_status_id smallint,
       result_status_msg text,
       result_my_type my_type
);

CREATE FUNCTION myfunc(....) RETURNS return_type_for_function ....

これは私がいつも行ってきた方法です。これは、OUT 変数を使用するよりも少し成熟しています。

以下に簡単な例を示します。

or_examples=# create table rel_examples.tabletest (id int);
CREATE TABLE

or_examples=# create table comp_table_test (test rel_examples.tabletest);
CREATE TABLE

or_examples=# create function test(int) returns comp_table_test
immutable language sql as $$
select row(row($1))::comp_table_test; $$;
CREATE FUNCTION
or_examples=# select test(1);
  test   
---------
("(1)")
(1 row)
于 2012-08-31T02:09:30.230 に答える
1

ただし、@Chris Travers は許容できる解決策を提案しました。私の場合、残念ながら f1 関数からデータを返すための新しい型を導入することはできませんでした。

それにもかかわらず、関数 f2() で関数 f1() を呼び出しても、次の構文を使用してデータを取得できます。

CREATE OR REPLACE FUNCTION f2(
    p_text text
)
  RETURNS record AS
$BODY$
DECLARE
    l_status_id smallint;
    l_status_msg text;
    l_my_type my_type;
    l_record record;
BEGIN
--some logic here

--this statement is okay now
  l_record = f1(p_text);
  l_status_id = l_record.result_status_id;
  l_status_msg = l_record.result_status_msg;
  l_my_type = l_record.result_my_type;

--logic continues here
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER
  COST 100;
于 2012-08-31T13:12:43.883 に答える
0

f2() 関数では、選択をレコード変数に実行し、そこから必要なものを抽出できます。たとえば、次のようになります。

CREATE OR REPLACE FUNCTION f2(p_text text )
  RETURNS record AS
$BODY$
DECLARE
    record_var record;
BEGIN
--this statement was failing
  SELECT * FROM f1(p_text) INTO record_var;

 SELECT l_my_type.result_my_type.d_int1; -- this should work

END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER
  COST 100;       
于 2012-08-30T17:48:12.453 に答える