我有一个像这样定义的表:
create table users (
id serial primary key,
name text,
email text,
);
...我想编写一个返回形状行的函数:
(
id integer,
name text,
email text,
some_other_column boolean,
)
我设法使用下面的代码,但我不想重新定义users表中的列:
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()
,它返回包含现有表和其他列的列的行。我不希望调用者确切地担心如何调用该函数。
我的假设是,因为我可以编写返回动态行的简单sql,所以我应该能够以某种方式将sql存储在数据库中,以保留返回行的结构。
答案 0 :(得分:2)
否。目前无法做到这一点(包括第10页)。
SQL是一种严格类型的语言。创建函数时,必须声明返回类型。要返回行(您可以使用SELECT * FROM srf()
调用):
您可以返回匿名记录(RETURNS SETOF record
)。但是,您必须在每次调用时提供列定义列表。
您可以返回多态(行)类型(RETURNS SETOF anyelement
)。但是你必须提供行类型(composite type)作为函数的参数,行类型需要在系统以某种方式注册。
您可以使用RETURNS SETOF
rowtype
明确使用任何已注册的行类型。副作用是该函数现在取决于行类型。
您可以使用RETURNS TABLE (...)
定义特定的返回行类型 - 您甚至可以在其中混合行类型(composite types)和简单类型。但是简单的SELECT * FROM srf()
不会分解嵌套的行类型 - 就像Mabu's answer一样可以证明。
相关:
这一切归结为:
有没有办法通过这样做来动态创建行类型?
不,没有。 SELECT * FROM ...
将从系统目录中检索列定义列表,其中行类型必须在之前注册,您可以通过这种方式调用函数。
通常,最好在RETURNS TABLE ()
子句中拼出列定义列表。这避免了依赖性。如果您需要快速注册基于现有表格的行类型而不拼写其列,则可以创建VIEW
- 或TEMPORARY VIEW
,如果它仅用于当前会话:< / p>
CREATE TEMP VIEW v_users_plus AS
SELECT *, NULL::boolean AS some_other_column FROM users;
这会在系统中注册同名行(v_users_plus
)的行类型,就像任何其他表或视图一样。对于非临时函数,显然您需要非临时行类型。
答案 1 :(得分:0)
您可以将表视为伪类型,但您必须在函数和调用此函数的查询中稍作更改,如下所示。
创建:
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();
实际上,您可以尝试使用其他返回类型作为动态结构,例如Refcursor或JSON ...这取决于您使用的语言或应用程序。