在pl/sql中,如果要返回資料的多個行,必須通過返回乙個ref cursor的游標,或者乙個資料集合(如臨時表或物理表)來完成,而ref cursor的侷限於可以從查詢中選擇的資料,而資料集合的侷限性在於必須先create table(無論是建立臨時表還是物理表)來進行具體化,具體化後,會因為頻繁刪除表導致大量的碎片。
oracle 9i開始,引入了管道化表函式,解決了這種情況。
管道化表函式是返回整個行的集合的函式,可以直接在sql中進行查詢,他就好像是真正的資料庫表一樣。他存在於記憶體中,比物理表速度要快幾十倍。
管道化表函式必須返回乙個集合,在函式中pipe row 語句被用來返回該集合的單個元素,該函式必須以乙個空的return語句結束,以表明他已經完成。一旦建立了該函式,就可以使用table()操作符從sql查詢中來呼叫它。
使用管道化表函式需要定義以下內容:
1. 定義乙個object型別的type
create type ty_obj as object ();
2. 定義乙個type繼承了這個ty_obj;
create type ta_obj as table of ty_obj;
3. 建立乙個管道化函式
create or replace function fun_name return ta_obj pipelined
isbegin
……pipe row ();
exception
end;
下面是乙個管道化表函式的例子。
create type ty_numlist as object(
n1 number,
n2 varchar2(50)
); create type ta_numlist as table of ty_numlist;
create or replace function fn_num return ta_numlist pipelined
isfv_numlist ty_numlist;
begin
for x in 1.. 20 loop
fv_numlist := ty_numlist(x, 'row'||x);
pipe row (fv_numlist);
end loop;
return;
end;
--接下來可以查詢結果了;
select * from table(fn_num);
這個管道化函式是可以帶引數的,比如:建立時,使用了id這個引數
create function my_fun(id number) return tt pipelined;
--那麼查詢時,可以這樣呼叫
select * from table(mu_fun(11));
下面是一些比較複雜的用法:把乙個查詢的結果通過管道化函式來返回。
1. 建立type
create or replace type ty_prov as object
(prov_id number(8),
prov_code varchar2(9),
eng_code varchar2(9),
prov_name varchar2(12)
)2. 建立type
create or replace type ta_prov as table of ty_prov
3.建立管道化函式
create or replace function getprovmsg(pp_code varchar2) return ta_prov pipelined
isfv_prov ty_prov;
begin
for x in (select prov_id, prov_code, eng_nm, prov_name from bam_t01_province_def where prov_code = pp_code) loop
fv_prov := ty_prov(x.prov_id, x.prov_code, x.eng_nm, x.prov_name);
pipe row (fv_prov);
end loop;
4. 使用下面語句來查詢
sql> select * from table(getprovmsg('100')) ;
prov_id prov_code eng_code prov_name
---------- --------- --------- ------------
10100 100 bj 北京
關於效率的小知識:
對於物理表,他的資料儲存在物理磁碟上,當資料第一次被read時,會被load到db cache中,根據lru演算法來決定這些資料會否置換出記憶體。如果資料一直在記憶體中,他會被所有session共享,由於資料是機構化的,所以在記憶體中掃瞄的效率是最高的。
對於臨時表,它和它的索引都是建立在臨時表空間上的,當在乙個session中第一次插入資料時,才開始在使用者的預設臨時表空間下分配臨時資料段,不同的session擁有不同的段,以保證不同會話不會相互影響。臨時表的資料也是結構化的,第一次讀取資料後,資料也會被cache到db cache中。
table()函式是9i的新特性,實際上是將乙個儲存在記憶體中的物件結構化後,使這個物件能以表的形式來查詢。物件是以流的方式儲存的,對流的結構化轉換會導致效率下降。所以它的效率應該低於存在於記憶體中的物理表和臨時表。(但應該高於第一次裝載入記憶體的物理表和臨時表)
以上參考自:
Oracle 管道化表函式
在pl sql中,如果要返回資料的多個行,必須通過返回乙個ref cursor的游標,或者乙個資料集合 如臨時表或物理表 來完成,而ref cursor的侷限於可以從查詢中選擇的資料,而資料集合的侷限性在於必須先create table 無論是建立臨時表還是物理表 來進行具體化,具體化後,會因為頻繁...
管道化表函式PIPELINED
為了讓 pl sql 函式返回資料的多個行,必須通過返回乙個 ref cursor 或乙個資料集合來完成。ref cursor 的這種情況侷限於可以從查詢中選擇的資料,而整個集合在可以返回前,必須進行具體化。oracle 9i 通過引入的管道化表函式糾正了後一種情況。表函式是返回整個行的集 通常作為...
oracle 管道流函式
管道流函式 1 先定義 物件類中 比如 create or replace type obj cjgzl is object mjvarchar2 20 民警 sspcsvarchar2 12 派出所 sqdmvarchar2 20 社群 fwslnumber 10 房屋數 czrksnumber ...