2016-03-28 23 views
0

sonra SETOF satırları SETOF satırları, bu tablodaki sonuçları ilk INSERTWHILE LOOP ve SELECT kullanarak bir tabloda bazı POSTGRESQL işlevi oluşturmaya çalışıyorum.WHILE LOOP bölüm

Bu sql örnektir: bana bu hatayı gösteren, select get_levels_test (3):

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; 

Sonra ben bu işlevi çağırmak için denemek

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 tablo sadece bir int sütununu içerir.

Bunun için, PostgreSQL 8.2.15 kullanıyorum (Greenplum Database 4.3.3.1 build 1).

cevap

0

Bir kompozit türüyle veya bir masala birlikte kullanılabilen "ileri geri" seçeneğini kullanmanız gerekir. Bunu kullanarak performans sorunları olabileceğinden lütfen bu özelliği dikkatli kullanın. Sonuçları başka bir tabloya katılmak için kullanmayın. Büyük veri setlerini bununla birlikte iade etmeyin. Kısa bir rapor gibi sadece çok küçük sonuçlar için kullanın.

Ayrıca, işlevinize istisna işleme eklemeniz gerekir. Bunu aşağıdaki örnek işlevime ekledim.

Örnek tablosu:

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

Örnek veriler:

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'); 

fonksiyon:

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; 

ve fonksiyonu kullanılarak:

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)