PostgreSQL:错误:42601:返回“记录”的函数需要列定义列表
据我所知,我的功能与我见过的示例非常相似。有人可以告诉我如何让它发挥作用吗?
create or replace function get_user_by_username(
username varchar(250),
online boolean
) returns setof record as $$
declare result record;
begin
if online then
update users
set last_activity = current_timestamp
where user_name = username;
end if;
return query
select
user_id,
user_name,
last_activity,
created,
email,
approved,
last_lockout,
last_login,
last_password_changed,
password_question,
comment
from
users
where
user_name = username
limit 1;
return;
end;
$$ language plpgsql;
As far as I can tell, my function properly resembles the samples I've seen. Can someone clue me in as to how I get this to work?
create or replace function get_user_by_username(
username varchar(250),
online boolean
) returns setof record as $
declare result record;
begin
if online then
update users
set last_activity = current_timestamp
where user_name = username;
end if;
return query
select
user_id,
user_name,
last_activity,
created,
email,
approved,
last_lockout,
last_login,
last_password_changed,
password_question,
comment
from
users
where
user_name = username
limit 1;
return;
end;
$ language plpgsql;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
返回选定的列
调用:
您已
DECLARE 结果记录;
但未使用该变量。我删除了那些残渣。您可以直接从
UPDATE
返回记录,这比调用额外的SELECT
语句要快得多。使用RETURN QUERY
和UPDATE
带有RETURNING
子句。如果用户不是
_online
,则默认为普通SELECT
。如果省略第二个参数,这也是(安全的)默认值 - 只有在函数定义中使用DEFAULT false
提供默认值后才可能实现。如果您在函数内部的查询中没有对列名 (
tablename.columnname
) 进行表限定,请注意列名和命名参数之间的命名冲突,这些冲突是可见的(大多数)在函数内随处可见。您还可以通过对参数使用位置引用 (
$n
) 来避免此类冲突。或者使用您从不使用的列名称前缀:例如下划线 (_username
)。如果
users.username
在表中被定义为unique,那么第二个查询中的LIMIT 1
就很糟糕了。如果不是,则UPDATE
可以更新多行,这很可能是错误。我假设一个唯一的用户名
并消除噪音。定义函数的返回类型(如 @ertx 所示),否则您必须为每个函数调用提供列定义列表,这很尴尬。
为此目的创建类型(如 @ertx 提出的)是一种有效的方法,但对于单个函数来说可能有点过分了。在我们使用
RETURNS TABLE
用于此目的 - 就像上面演示的那样。对于这个简单的函数,您不需要循环。
每个函数都需要一个语言声明。在这种情况下,
LANGUAGE plpgsql
。我使用
timestamptz
(带时区的时间戳
)而不是timestamp
(不带时区的时间戳
),这是理智的默认值。请参阅:返回(一组)整行
要返回现有表
users
的所有列,有一个更简单的方法。 Postgres 自动为每个表定义一个同名的复合类型。只需使用RETURNS SETOF users
即可大大简化查询:返回整行加上自定义添加
要解决 TheRealChx101 在下面的评论中添加的问题:
Return selected columns
Call:
You had
DECLARE result record;
but didn't use the variable. I deleted the cruft.You can return the record directly from the
UPDATE
, which is much faster than calling an additionalSELECT
statement. UseRETURN QUERY
andUPDATE
with aRETURNING
clause.If the user is not
_online
, default to a plainSELECT
. This is also the (safe) default if the second parameter is omitted - which is only possible after providing that default withDEFAULT false
in the function definition.If you don't table-qualify column names (
tablename.columnname
) in queries inside the function, be wary of naming conflicts between column names and named parameters, which are visible (most) everywhere inside a function.You can also avoid such conflicts by using positional references (
$n
) for parameters. Or use a prefix that you never use for column names: like an underscore (_username
).If
users.username
is defined unique in your table, thenLIMIT 1
in the second query is just cruft. If it is not, then theUPDATE
can update multiple rows, which is most likely wrong. I assume a uniqueusername
and trim the noise.Define the return type of the function (like @ertx demonstrated) or you have to provide a column definition list with every function call, which is awkward.
Creating a type for that purpose (like @ertx proposed) is a valid approach, but probably overkill for a single function. That was the way to go in old versions of Postgres before we had
RETURNS TABLE
for that purpose - like demonstrated above.You do not need a loop for this simple function.
Every function needs a language declaration.
LANGUAGE plpgsql
in this case.I use
timestamptz
(timestamp with time zone
) instead oftimestamp
(timestamp without time zone
), which is the sane default. See:Return (set of) whole row(s)
To return all columns of the existing table
users
, there is a simpler way. Postgres automatically defines a composite type of the same name for every table. Just useRETURNS SETOF users
to vastly simplify the query:Return whole row plus custom addition
To address the question added by TheRealChx101 in a comment below:
Not as simple, but doable. We can send the whole row type as one field, and add more:
The "magic" is in the function call, where we (optionally) decompose the row type:
db<>fiddle here (showing all)
If you need something more "dynamic", consider:
如果您想创建返回 setof 记录的函数,则需要在 select 语句中定义列类型
更多信息
您的查询应如下所示:(
您可能需要更改数据类型)
我个人更喜欢类型方法。它确保如果编辑该函数,所有查询都将返回正确的结果。这可能会很痛苦,因为每次修改函数的参数时,您都需要重新创建/删除类型。
例如:
if you would like to create function returning setof record, you'll need to define column types in your select statement
More info
Your query should look something like this:
(you will probably need to change the data types)
I personaly prefer the types approach. it assures that if the function is edited, all the queries will return correct results. It might be a pain because every time you modify function's arguments you'll need to recreate/drop types aswell tho.
Eg:
更改
为
在你的情况下它将是
Change
to
In your case it would be
我创建了
my_func()
,它使用 [RETURN NEXT][1] 或 [RETURN QUERY][1] 语句返回SETOF RECORD
类型,如下所示:或者:
然后,调用
my_func()
得到了相同的错误,如下所示:因此,我在
my_func()
之后使用AS
设置了一个列定义列表,然后我可以调用my_func()
时不会出现错误,如下所示:此外,在不使用
FROM
子句的情况下调用my_func()
会出现语法错误,如下所示:并且,在没有
FROM
子句和列定义列表的情况下调用my_func()
会出现[错误][2],如下所示:I created
my_func()
which returnsSETOF RECORD
type with a [RETURN NEXT][1] or [RETURN QUERY][1] statement as shown below:Or:
Then, calling
my_func()
got the same error as shown below:So, I set a column definition list just after
my_func()
withAS
, then I could callmy_func()
without error as shown below:In addition, calling
my_func()
without aFROM
clause got the syntax error as shown below:And, calling
my_func()
without aFROM
clause and column definition list got [the error][2] as shown below: