如何 return 一个 table 的行类型加上一个函数的附加列?

How to return a table's rowtype plus an additional column from a function?

我有一个 table 定义如下:

create table users (
  id serial primary key,
  name text,
  email text,
);

...我想编写一个函数,其中 returns 行的形状为:

(
  id integer,
  name text,
  email text,
  some_other_column boolean,
)

我设法使用下面的代码实现了这一点,但我不想重新定义用户的列 table:

create or replace function get_users () 
returns table (
  id integer,
  name text,
  email text,
  some_other_column boolean,
) as $$
    select users.*, true as some_other_column from users;
$$ language sql;

有没有办法通过执行类似的操作来动态创建行类型? (postgres 抱怨 users.* 处的语法错误):

create or replace function get_users () 
returns table (
  users.*, 
  some_other_column boolean
) as $$
    select users.*, true as some_other_column from users;
$$ language sql;

请注意,直接执行以下查询就可以正常工作:

select users.*, true as some_other_column from users;

这里的最终目标是最终得到一个像 select * from get_users() 这样的可调用函数,其中 returns 行包括现有 table 中的列和其他列。我不希望调用者担心究竟如何调用该函数。

我的假设是,由于我可以编写简单的 sql returns 动态行,所以我应该能够以某种方式将 sql 存储在数据库中,从而保留返回行的结构。

您可以将 table 视为伪类型,但您必须对函数和调用此函数的查询进行一些更改,如下所示。

正在创建:

create or replace function get_users () 
returns table (
  row_users users, 
  some_other_column boolean
) as $$
    select t, true as some_other_column from users as t;
$$ language sql;

通话中:

SELECT (row_users).*, some_other_column FROM get_users();

事实上,您可以尝试另一种 return 类型的动态结构,例如 Refcursor or JSON ...这取决于您使用的语言或应用程序。

否。 目前没有办法做到这一点(包括第 10 页)。

SQL 是一种严格类型的语言。创建函数时,必须声明 return 类型。要 return 一组 (您可以用 SELECT * FROM srf() 调用):

  • 您可以 return 匿名记录 (RETURNS SETOF record)。但是你必须在每次调用时提供一个列定义列表。

  • 您可以 return 多态(行)类型 (RETURNS SETOF anyelement)。但是您必须提供行类型 (composite type) 作为函数的参数,并且行类型需要以某种方式在系统中注册 .

    • Refactor a PL/pgSQL function to return the output of various SELECT queries
  • 您可以明确使用任何已注册的行类型,RETURNS SETOFrowtype。副作用是函数现在取决于行类型。

  • 您可以使用 RETURNS TABLE (...) 临时定义 returned 行类型 - 您甚至可以混合行类型(composite types) and simple types. But a simple SELECT * FROM srf() will not decompose nested row types - like Mabu's answer 去演示。

相关:

  • Return SETOF rows from PostgreSQL function

归结为:

Is there a way to dynamically create a row type by doing something like this?

不,没有。 SELECT * FROM ... 将从系统目录中检索列定义列表,其中行类型必须在 之前注册 您可以这样调用该函数。

通常最好在 RETURNS TABLE () 子句中拼出列定义列表。这避免了依赖性。如果您需要根据现有 table 快速注册行类型而不拼写其列,您可以创建 VIEW - 或者 TEMPORARY VIEW 如果它仅用于当前会话:

CREATE TEMP VIEW v_users_plus AS
SELECT *, NULL::boolean AS some_other_column FROM users;

这会在系统中注册同名 (v_users_plus) 的行类型,就像任何其他 table 或视图一样。对于非临时函数,显然需要非临时行类型。