1. 程式人生 > >PostgreSQL函數如何返回數據集 [轉]

PostgreSQL函數如何返回數據集 [轉]

code 示例 intern 不同 nbsp name || spa begin

PostgreSQL函數如何返回數據集

以下主要介紹PostgreSQL函數/存儲過程返回數據集,或者也叫結果集的示例。

背景: PostgreSQL裏面沒有存儲過程,只有函數,其他數據庫裏的這兩個對象在PG裏都叫函數。 函數由函數頭,體和語言所組成,函數頭主要是函數的定義,變量的定義等,函數體主要是函數的實現,函數的語言是指該函數實現的方式,目前內置的有c,plpgsql,sql和internal,可以通過pg_language來查看當前DB支持的語言,也可以通過擴展來支持python等

函數返回值一般是類型,比如return int,varchar,返回結果集時就需要setof來表示。


一、數據準備

create table department(id int primary key, name text);
create table employee(id int primary key, name text, salary int, departmentid int references department);

insert into department values (1, Management),(2, IT),(3, BOSS);

insert into employee values (1, kenyon, 30000, 1
); insert into employee values (2, francs, 50000, 1); insert into employee values (3, digoal, 60000, 2); insert into employee values (4, narutu, 120000, 3);

二、例子
1.sql一例

create or replace function f_get_employee() 
returns setof employee 
as 
$$
select * from employee;
$$
language sql;

等同的另一個效果(Query)

create or replace function f_get_employee_query() 
returns setof employee 
as 
$$
begin
return query select * from employee;
end;
$$
language plpgsql;

查詢圖解如下

postgres=# select * from f_get_employee();
 id |  name  | salary | departmentid 
----+--------+--------+--------------
  1 | kenyon |  30000 |            1
  2 | francs |  50000 |            1
  3 | digoal |  60000 |            2
  4 | narutu | 120000 |            3
(4 rows)

查詢出來的函數還可以像普通的表一樣按條件查詢 ,但如果查詢的方式不一樣,則結果也不一樣,以下查詢方式將會得到類似數組的效果

postgres=# select f_get_employee();
   f_get_employee    
---------------------
 (1,kenyon,30000,1)
 (2,francs,50000,1)
 (3,digoal,60000,2)
 (4,narutu,120000,3)
(4 rows)

因為返回的結果集類似一個表的數據集,PostgreSQL還支持對該函數執行結果進行條件判斷並過濾

postgres=# select * from f_get_employee() where id >3;
 id |  name  | salary | departmentid 
----+--------+--------+--------------
  4 | narutu | 120000 |            3
(1 row)

上面的例子相對簡單,如果要返回不是表結構的數據集該怎麽辦呢?看下面

2.返回指定結果集

--a.用新建type來構造返回的結果集

--新建的type在有些圖形化工具界面中可能看不到,
--要查找的話可以通過select * from pg_class where relkind=‘c‘去查,c表示composite type

create type dept_salary as (departmentid int, totalsalary int);

create or replace function f_dept_salary() 
returns setof dept_salary 
as
$$
declare
rec dept_salary%rowtype;
begin
for rec in select departmentid, sum(salary) as totalsalary from f_get_employee() group by departmentid loop
  return next rec;
  end loop;
return;
end;
$$
language plpgsql;

--b.用Out傳出的方式

create or replace function f_dept_salary_out(out o_dept text,out o_salary text) 
returns setof record as
$$
declare
    v_rec record;
begin
    for v_rec in select departmentid as dept_id, sum(salary) as total_salary from f_get_employee() group by departmentid loop
        o_dept:=v_rec.dept_id;
        o_salary:=v_rec.total_salary;  
        return next;
    end loop; 
end;
$$
language plpgsql;

--執行結果:

postgres=# select * from f_dept_salary();
 departmentid | totalsalary 
--------------+-------------
            1 |       80000
            3 |      120000
            2 |       60000
(3 rows)

postgres=# select * from f_dept_salary_out();
 o_dept | o_salary 
--------+----------
 1      | 80000
 3      | 120000
 2      | 60000
(3 rows)

--c.根據執行函數變量不同返回不同數據集

create or replace function f_get_rows(text) returns setof record as
$$
declare
rec record;
begin
for rec in EXECUTE select * from  || $1 loop
return next rec;
end loop;
return;
end
$$
language plpgsql;

--執行結果:

postgres=# select * from f_get_rows(department) as dept(deptid int, deptname text);
 deptid |  deptname  
--------+------------
      1 | Management
      2 | IT
      3 | BOSS
(3 rows)

postgres=# select * from f_get_rows(employee) as employee(employee_id int, employee_name text,employee_salary int,dept_id int);
 employee_id | employee_name | employee_salary | dept_id 
-------------+---------------+-----------------+---------
           1 | kenyon        |           30000 |       1
           2 | francs        |           50000 |       1
           3 | digoal        |           60000 |       2
           4 | narutu        |          120000 |       3
(4 rows)

這樣同一個函數就可以返回不同的結果集了,很靈活。

PostgreSQL函數如何返回數據集 [轉]