PostgreSQL:错误:42601:返回“记录”的函数需要列定义列表

PostgreSQL:错误:42601:返回“记录”的函数需要列定义列表,postgresql,parameter-passing,plpgsql,set-returning-functions,Postgresql,Parameter Passing,Plpgsql,Set Returning Functions,据我所知,我的函数与我所看到的示例非常相似。有人能告诉我怎么做吗 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_a

据我所知,我的函数与我所看到的示例非常相似。有人能告诉我怎么做吗

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;

如果要创建函数返回记录集,则需要在select语句中定义列类型

您的查询应该如下所示:

select * from get_user_by_username('Username', True) as 
  f(user_id integer, user_name varchar, last_activity, varchar, created date, email        archar, approved boolean, last_lockout timestamp, last_login timestamp, 
  last_password_changed timestamp, password_question varchar, comment varchar)
您可能需要更改数据类型

我个人更喜欢类型方法。它确保如果编辑函数,所有查询都将返回正确的结果。这可能是一种痛苦,因为每次修改函数的参数时,都需要重新创建/删除类型

例如:

返回所选列 创建或替换函数get_user_by_username_username text ,\u联机bool默认值为false 返回表 用户id int ,用户名varchar ,最后一项活动 语言plpgsql AS $func$ 开始 如果你在线的话 返回查询 更新用户u 设置最后\u活动=当前\u时间戳-带时区的ts 其中u.user\u name=\u username 正在返回u.user\u id ,u.user\u名称 最后一次活动; 其他的 返回查询 选择u.user\u id ,u.user\u名称 ,u.last_活动 来自用户u 其中u.user\u name=\u username; 如果结束; 终止 $func$; 电话:

您已申报成绩记录;但是没有使用变量。我删除了积垢

您可以直接从更新返回记录,这比调用额外的SELECT语句快得多。使用返回查询和

如果用户不在线,则默认为普通选择。如果省略了第二个参数,这也是安全的默认值-只有在函数定义中使用default false提供该默认值后才可能

如果在函数内部的查询中没有对列名tablename.columnname进行表限定,请注意列名和命名参数之间的命名冲突,因为在函数中,列名和命名参数在任何地方都是可见的。 还可以通过对参数使用位置引用$n来避免此类冲突。或者使用从未用于列名的前缀:例如下划线\用户名

如果在表中定义的users.username是唯一的,那么第二个查询中的限制1就是错误的。如果不是,则更新可以更新多行,这很可能是错误的。我假设一个唯一的用户名,并消除噪音

定义像@ertx这样的函数的返回类型,或者必须为每个函数调用提供一个列定义列表,这很尴尬

为此目的创建一个类型(如@ertx)是一种有效的方法,但对于单个函数来说可能有些过分。这是我们之前在旧版本的博士后考试中所采用的方法,就像上面演示的那样

这个简单函数不需要循环

每个函数都需要一个语言声明。在本例中为plpgsql语言

我使用带时区的timestamp timestamp,而不是不带时区的timestamp timestamp timestamp,这是正常的默认值。见:

整行返回集 要返回现有表用户的所有列,有一种更简单的方法。Postgres会自动为每个表定义一个同名的复合类型。只需使用一组用户即可大大简化查询:

创建或替换函数get_user_by_username_username text ,\u联机bool默认值为false 返回一组用户 语言plpgsql AS $func$ 开始 如果你在线的话 返回查询 更新用户u 设置最后\u活动=当前\u时间戳 其中u.user\u name=\u username 返回u.*; 其他的 返回查询 挑选* 来自用户u 其中u.user\u name=\u username; 如果结束; 终止 $func$; 返回整行加上自定义添加 要解决ALCHX101在以下评论中添加的问题:


如果在整个表之外还有一个计算值呢?该示例如何定义列类型?在我看来,它只是插入行。返回查询不应该将结果发送回去吗?你能给我一个例子,我将如何改变我的功能,以满足要求?谢谢。。。我不知道为什么我所看到的任何文档中都没有显示。您也可以使用参数,这类工作类似于声明类型,但您不必管理单独的对象。如本文所述,您还可以定义一个自定义类型,并将其与json_populate_record结合使用,以在不使用plpgsql的情况下实现相同的功能—非常干净。Ertx把我带到了一个地方,在那里我可以找出剩下的,但这是一篇优秀的文章。我希望它能为其他PostgreSQL新手消除一些困惑。如果除了一个完整的表之外还有一个计算值呢@疗法
ealChx101:我添加了第三个解决方案来解决这个问题。谢谢。这很有帮助。你就像数据库里的耶稣一样。有时候我想知道你脑子里在想什么,哈哈哈。
CREATE TYPE return_type as 
(user_id integer,
 user_name varchar,
 last_activity varchar,
 created timestamp,
 email varchar,
 approved boolean,
 last_lockout timestamp ,
 last_login timestamp,
 last_password_changed timestamp,
 password_question varchar,
 comment varchar);

create or replace function get_user_by_username( username varchar(250), online 

boolean) returns setof return_type as $$
declare _rec return_type;
begin
    if online then 
        update users
        set last_activity = current_timestamp
        where user_name = username;
    end if;
    for _rec in 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 
    loop

      return next _rec;

    end loop

end;
$$ language plpgsql;
SELECT * FROM get_user_by_username('myuser', true);