在WHILE LOOP部分之后从PostgreSQL函数返回SETOF行

时间:2016-03-28 12:58:16

标签: function greenplum postgresql-8.2

我正在尝试创建一个POSTGRESQL函数,该函数首先INSERT使用WHILE LOOP表格中的某些数据,然后使用SELECT此表的结果。

这是一个sql示例:

CREATE OR REPLACE FUNCTION get_levels_test (maxlevel int) RETURNS SETOF list_of_levels  AS $$
DECLARE
    level int = 1;
BEGIN
 TRUNCATE list_of_levels;

 WHILE (level <= maxlevel) LOOP
    INSERT INTO list_of_levels
        SELECT level;             

    level = level + 1;
 END LOOP;
    select * from list_of_levels;
END;
$$ LANGUAGE PLPGSQL VOLATILE;

然后我尝试用select get_levels_test (3)调用此函数,它显示了这个错误:

ERROR: query has no destination for result data
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Where: PL/pgSQL function "get_levels_test" line 12 at SQL statement

list_of_levels表仅包含int列。

如果需要,我使用的是PostgreSQL 8.2.15(Greenplum Database 4.3.3.1 build 1)。

1 个答案:

答案 0 :(得分:0)

您需要使用&#34;返回&#34;可以与复合类型或表格一起使用。请谨慎使用此功能,因为使用此功能可能会导致性能问题。不要使用它将结果连接到另一个表。不要使用此返回大型数据集。仅用于非常小的结果,例如简短的报告。

您还需要在函数中添加异常处理。我将此添加到下面的示例函数中。

示例表:

    create table employees
    (id int not null,
     manager_id int null,
     employee_title text not null)
     distributed by (id);

示例数据:

    insert into employees values
    (1, null, 'President'),
    (2, 1, 'Vice-President'),
    (3, 2, 'Manager'),
    (4, 3, 'Engineer'),
    (5, null, 'CMO'),
    (6, 5, 'Director'),
    (7, 6, 'Assistant'),
    (8, 7, 'Developer');

功能:

    create or replace function get_employees(p_id int) returns setof employees as
    $$
    declare
            v_function_name text := 'get_employees';
            v_location int;
            v_rec record;
            v_rec2 employees;
            v_id employees.id%type;
    begin
            v_location := 1000;
            create temporary table t1
            (id integer) on commit drop distributed by (id);

            v_location := 2000;
            for v_rec in (select id from employees where id = p_id and manager_id is null order by id) loop
                    v_id := v_rec.id;
                    insert into t1 values (v_id);
                    while v_id is not null loop
                            select id into v_id from employees where manager_id = v_id;
                            if v_id is not null then
                                    insert into t1 values (v_id);
                            end if;
                    end loop;
            end loop;

            v_location := 3000;
            for v_rec2 in (select * from employees e join t1 on e.id = t1.id order by e.id) loop
                    return next v_rec2;
            end loop;
    exception
      when others then
        raise exception '(%:%:%)', v_function_name, v_location, sqlerrm;
    end;
    $$
    language plpgsql;

使用功能:

    select * From get_employees(1);
     id | manager_id | employee_title 
    ----+------------+----------------
      1 |            | President
      2 |          1 | Vice-President
      3 |          2 | Manager
      4 |          3 | Engineer
    (4 rows)


    select * From get_employees(5);
     id | manager_id | employee_title 
    ----+------------+----------------
      5 |            | CMO
      6 |          5 | Director
      7 |          6 | Assistant
      8 |          7 | Developer
    (4 rows)
相关问题