如何创建返回多行的PL / pgSQL函数

时间:2012-06-10 21:54:47

标签: postgresql stored-procedures plpgsql return-type postgresql-8.4

我正在尝试创建a PL/pgSQL function,它应填充一个临时表,然后从中返回所有行(稍后将是一个连接),但我不知道要为它指定哪种返回类型:

create or replace function pref_daily_misere() returns void as $BODY$
        begin

        create temporary table temp_best (id varchar not null) on commit drop;
        insert into temp_best (id) select id from pref_money where
            yw = to_char(current_timestamp - interval '1 week', 'IYYY-IW')
            order by money desc limit 10;
        select id from temp_best;
        end;
$BODY$ language plpgsql;

上述陈述单独运作,但给我错误

# select pref_daily_misere();
ERROR:  query has no destination for result data
HINT:  If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT:  PL/pgSQL function "pref_daily_misere" line 7 at SQL statement

当我尝试在PostgreSQL 8.4.11数据库中调用它时。

这可能是因为我错误地指定了上面的返回void ,但我不知道要使用哪种返回类型而忽略返回类型是编译错误。

1 个答案:

答案 0 :(得分:5)

您希望在函数内部使用setof varchar返回类型,然后使用return query ...。来自fine manual

  

<强> 39.6.1.2。返回下一步并返回查询

RETURN NEXT expression;
RETURN QUERY query;
RETURN QUERY EXECUTE command-string [ USING expression [, ... ] ];
     

当声明PL / pgSQL函数返回SETOF sometype 时,要遵循的过程略有不同。在这种情况下,要返回的各个项由一系列RETURN NEXTRETURN QUERY命令指定,然后使用不带参数的最终RETURN命令来指示该函数已完成执行。

我想你想要更像这样的东西:

create or replace function pref_daily_misere() returns setof varchar as $BODY$
begin
    create temporary table temp_best (id varchar not null) on commit drop;
    insert into temp_best (id)
    select id
    from pref_money
    where yw = to_char(current_timestamp - interval '1 week', 'IYYY-IW')
    order by money
    desc limit 10;
    return query select id from temp_best;
    return;
end;
$BODY$ language plpgsql;

然而,临时表在这里毫无意义:

  

注意: RETURN NEXTRETURN QUERY的当前实现会在从函数返回之前存储整个结果集,如上所述。

因此PostgreSQL正在计算整个结果集并自行缓存它。你可以这样做:

create or replace function pref_daily_misere() returns setof varchar as $BODY$
begin
    return query
        select id
        from pref_money
        where yw = to_char(current_timestamp - interval '1 week', 'IYYY-IW')
        order by money
        desc limit 10;
    return;
end;
$BODY$ language plpgsql;

我很确定无论如何都会在你的函数结束时删除临时表,所以你应该摆脱它。