如何从函数返回表的行类型和附加列?

x1f*_*577 6 postgresql return-type plpgsql set-returning-functions

我有一个像这样定义的表:

create table users (
  id serial primary key,
  name text,
  email text,
);
Run Code Online (Sandbox Code Playgroud)

...我想编写一个返回形状行的函数:

(
  id integer,
  name text,
  email text,
  some_other_column boolean,
)
Run Code Online (Sandbox Code Playgroud)

我设法使用下面的代码使其工作,但我宁愿不重新定义用户表中的列:

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

有没有办法通过执行这样的操作来动态创建行类型?(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;
Run Code Online (Sandbox Code Playgroud)

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

select users.*, true as some_other_column from users;
Run Code Online (Sandbox Code Playgroud)

这里的最终目标是得到一个可调用的函数select * from get_users(),它返回包含现有表中的列和附加列的行。我不希望调用者担心究竟如何调用函数。

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

Erw*_*ter 6

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

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

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

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

  • 您可以显式使用任何已注册的行类型,带有RETURNS SETOFrowtype. 副作用是该函数现在取决于行类型。

  • 您可以特别定义返回的行类型RETURNS TABLE (...)- 您甚至可以在其中混合行类型(复合类型)和简单类型。但是一个简单的SELECT * FROM srf()不会分解嵌套的行类型 - 就像Mabu's answer 所证明的那样。

有关的:

这一切都归结为:

有没有办法通过执行这样的操作来动态创建行类型?

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

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

CREATE TEMP VIEW v_users_plus AS
SELECT *, NULL::boolean AS some_other_column FROM users;
Run Code Online (Sandbox Code Playgroud)

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