Postgres:"错误:RETURN在函数返回集合中没有参数"在递归函数中

时间:2016-10-24 15:33:51

标签: postgresql

我非常非常擅长编写Postgres函数。我通过从孩子的id开始递归地搜索父母来编写一个函数来为孩子建立物化路径。这是我的功能,但我不断收到错误ERROR: RETURN cannot have a parameter in function returning set

create or replace function build_mp(child_id text)
returns SETOF text 
language plpgsql
as $$
begin
    select parentid from account where childid = child_id;
    if parentid IS NULL then
        return ARRAY[child_id];
    else
        return build_mp(parentid) || ARRAY[child_id];
    end if;
end $$;

SELECT build_mp('mychild');

我做错了什么?

修改

这是工作解决方案。它需要一个孩子的id,然后递归搜索它上面的所有父母,为新的子项建立一个物质路径。

create or replace function build_mp(child_id text)
returns text[] 
language plpgsql
as $$
declare
    parent text;
begin
    execute 'select parentid from account where childid = $1' INTO parent USING child_id;
    if parent IS NULL THEN
        return ARRAY[child_id];
    else
        return build_mp(parent) || ARRAY[child_id];
    end if;
end $$;

SELECT build_mp('mychild') AS mp;

2 个答案:

答案 0 :(得分:3)

要克服" 错误:查询没有结果数据的目的地"错误,你不需要动态SQL。

你可以select into a variable directly

select parentid into parent from account where childid = child_id;

但是您可以使用recursive CTE和SQL函数来简化您的功能。这将会表现得更好,尤其是在大量关卡中:

create or replace function build_mp(child_id text)
  returns text[]
language sql
as 
$$
   with recursive all_levels (childid, parentid, level) as (
      select childid, parentid, 1
      from account
      where childid = child_id
      union all
      select c.childid, c.parentid, p.level + 1
      from account c
       join all_levels p on p.parentid = c.childid
   )
   select array_agg(childid order by level)
   from all_levels;
$$;

答案 1 :(得分:1)

如果要返回text数组,则必须将该函数声明为

... RETURNS text[]

而不是

... RETURNS SETOF text

set return函数返回一个表,而数组是text[]类型的单个值。在set return函数中,您将为返回的每一行使用RETURN NEXT child_id并使用RETURN(不带参数)来终止函数处理。

PostgreSQL抱怨你在集合返回函数中使用RETURN value,这是不允许的。