ORACLE管道化表函式

2021-08-01 17:29:35 字數 2747 閱讀 3190



在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 ...