声明PL/pgSQL中记录的元组结构

nny*_*yby 3 postgresql plpgsql postgresql-9.1

我在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;
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 12

您正在混合返回SETOF值的语法以及返回单个行或值的语法.

- 一个相关的问题是 - 如何从中返回单个记录'r'

使用声明函数时RETURNS TABLE,必须RETURN NEXT在正文中使用返回行(或标量值).如果你想使用一个record变量,它必须匹配返回类型.请进一步参考代码示例.

返回单个值或行

如果您只想返回单行,则不需要未定义类型的记录.@Kevin已经展示了两种方式.我将添加一个带OUT参数的简化版本:

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

您甚至不需要添加RETURN;函数体,声明OUT参数的值将在函数结束时自动返回 - NULL对于尚未分配的任何参数.
而且您不需要声明,RETURNS RECORD因为OUT参数已经清楚了.

返回一组行

如果您确实想要返回行(包括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;
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT * FROM my_func() AS x(a int, b text);
Run Code Online (Sandbox Code Playgroud)

但这非常难以处理,因为您必须为每次调用提供列定义列表.它通常可以用更优雅的东西代替:

  • 如果您在创建函数时知道类型,请立即声明它(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;
Run Code Online (Sandbox Code Playgroud)

你的问题不清楚你究竟需要什么.