返回类型的简单方法是SETOF表加上其他字段?

Mic*_*elF 2 postgresql plpgsql composite-types postgresql-9.2

我正在编写一个PL / pgSQL存储过程,该过程将返回一组记录。每个记录都包含现有表的所有字段(将其称为Retailer,该字段具有两个字段:retailer_key和retailer_name)。这当然有效:

CREATE FUNCTION proc_Find_retailers
 (IN p_Store_key INT)
   RETURNS SETOF Retailer
   AS $$ ...`
Run Code Online (Sandbox Code Playgroud)

现在,我想更新sp,以便它在每个返回的记录的'end'处返回另外两个字段。我可以做一些事情,例如:

CREATE FUNCTION proc_Find_store
 (IN p_Store_key INT)
   RETURNS TABLE (
      retailer_key int,
      retailer_name varchar(50),
      addl_field_1 int,
      addl_field_2 double precision)
   AS $$ ...
Run Code Online (Sandbox Code Playgroud)

在现实世界中,我的Retailer表具有50个字段(在我的示例中没有这两个字段),因此枚举RETURNS TABLE子句中的所有这些字段很繁琐。有没有捷径可走,所以我可以这样说:(我意识到我在这里编造的东西在语法上是非法的,但我这样做是为了让您有我所寻找的味道):

CREATE FUNCTION proc_Find_store
 (IN p_Store_key INT)
   RETURNS (SETOF Store,
      addl_field_1 int,
      addl_field_2 double precision)
   AS $$ ...
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 6

可以返回整行作为复合类型并添加更多内容:

CREATE OR REPLACE FUNCTION f_rowplus()
  RETURNS TABLE (rec demo, add_int int, add_txt text) AS
$func$
SELECT d, 5, 'baz'::text FROM demo d;
$func$  LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)

但是,当您使用简单调用时:

SELECT * FROM f_rowplus();
Run Code Online (Sandbox Code Playgroud)

您从表中获得该行demo作为单独的复合类型。您必须致电:

SELECT (rec).*,  add_int, add_txt FROM f_rowplus();
Run Code Online (Sandbox Code Playgroud)

获取所有单独的列。需要括号。

另外:这仍然只对函数求值一次 -像这样的直接调用将对返回类型中的每一列求值一次:

SELECT (f_rowplus()).*;
Run Code Online (Sandbox Code Playgroud)

细节:

Postgres在这里有点不一致。如果您使用创建函数

CREATE OR REPLACE FUNCTION f_row2()
  RETURNS TABLE (rec demo) AS
...
Run Code Online (Sandbox Code Playgroud)

然后将其默默转换为单独的列(分解)。仍然没有链接到原始复合类型。您根本无法引用声明的输出列rec,因为该列已被分解类型的列替换。该调用将导致错误消息:

SELECT rec FROM f_row2();
Run Code Online (Sandbox Code Playgroud)

同样在这里:

CREATE OR REPLACE FUNCTION f_row3(OUT rec demo)
  RETURNS SETOF demo AS
...
Run Code Online (Sandbox Code Playgroud)

然而,一旦你添加任何更多的OUT列,复合型被保留作为申报(不分解),您可以:

SELECT rec FROM f_rowplus();
Run Code Online (Sandbox Code Playgroud)

具有第一个功能。

我创建了一个SQL Fiddle,演示了这些变体。


除了
当使用功能在返回多个列FROM列表(表函数),并在分解SELECT列表是这样的:

SELECT (rec).* FROM f_rowplus();
Run Code Online (Sandbox Code Playgroud)

...该函数仍仅被评估一次 - 像这样直接在列表中进行调用分解SELECT

SELECT (f_rowplus()).*;  -- also: different result
Run Code Online (Sandbox Code Playgroud)

...将对返回类型中的每一列求值一次。细节: