在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 astable
of ty_obj;
3. 建立乙個管道化函式
createorreplace
function fun_name return
ta_obj pipelined
isbegin
……
pipe
row ();
exception
end;
下面是乙個管道化表函式的例子。
create type ty_numlist asobject(
n1
number
, n2
varchar2(50));
create type ta_numlist as
table
ofty_numlist;
create
orreplace
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);
endloop;
return
;end;--
接下來可以查詢結果了;
select
*from
table(fn_num);
這個管道化函式是可以帶引數的,比如:建立時,使用了id這個引數
createfunction my_fun(id number) return
tt pipelined;
--那麼查詢時,可以這樣呼叫
select
*from
table(mu_fun(11));
下面是一些比較複雜的用法:把乙個查詢的結果通過管道化函式來返回。
1. 建立type
createorreplace type ty_prov as
object
( prov_id
number(8
), prov_code
varchar2(9
), eng_code
varchar2(9
), prov_name
varchar2(12))
2. 建立type
createorreplace type ta_prov as
table
of ty_prov
3.建立管道化函式
createorreplace
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);
endloop;
return;
exception
when others then
-20001,'
getprovmsg : '||
sqlerrm );
end;
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的新特性,實際上是將乙個儲存在記憶體中的物件結構化後,使這個物件能以表的形式來查詢。物件是以流的方式儲存的,對流的結構化轉換會導致效率下降。所以它的效率應該低於存在於記憶體中的物理表和臨時表。(但應該高於第一次裝載入記憶體的物理表和臨時表)
關於對記憶體的影響:
網上幾乎沒有資料提及這個table()特性對sga和pga造成的嚴重影響。所以我們暫且忽略吧。或者有高手幫忙補充補充~!
from:封燁
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 ...