【问题标题】:Return SETOF rows from PostgreSQL function after WHILE LOOP section在 WHILE LOOP 部分之后从 PostgreSQL 函数返回 SETOF 行
【发布时间】:2016-03-28 12:58:16
【问题描述】:

我正在尝试创建一个 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)。

【问题讨论】:

    标签: function greenplum postgresql-8.2


    【解决方案1】:

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

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

    示例表:

        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)
    

    【讨论】:

      猜你喜欢
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-25
      相关资源
      最近更新 更多