Oracle Pipelined Table Functions簡介

來源:互聯網
上載者:User

//概況  
//基本上,當你希望一個PLSQL(或者java或者c)程式作為資料來源,而不是表,  
//你可能會用到管道函數(pipelined function).  
//pipelined function操作起來就像一張表  
//一個pl/sql函數可能會用於資料倉儲的資料庫裡面,轉換大量的資料。  
//這可能包括格式化一系列轉換資料,它們是不同的函數執行後得到的結果。  
//在Oracle database 9i之前,大量的資料轉換,既需要顯著的記憶體開銷,  
//又需要在轉換的每個階段將資料存放區在中間表裡面。在這兩種情況下,  
//載入進程都會致使效能的下降。 

//使用PL/SQL表函數,可以在資料轉換的時候有效減少開銷。PL/SQL表函數  
//可以接收和返回多行,交付這些資料,當他們準備好的時候,而不是一次性的處理;  
//而且PL/SQL表函數還可以並存執行操作。  
--  
//執行個體1:產生隨機數  
//你怎麼樣用一條sql語句產生在1-49之間的互不相同的隨機數呢?  
//我們可能從一組已經產生的數中去查詢(注意下面的最內層的查詢);  
//任何擁有大於等於49行記錄的表都可以做到。若不使用管道函數的話,下面是最好的解決辦法:  
select r  
  from (select r  
           from (select rownum r  
                   from all_objects  
                  where rownum < 50)  
          order by dbms_random.value)  
where rownum <= 6;  
/  
         R  
----------  
        36  
        40  
        30  
        26  
         3  
        42  
//我們將最內部的查詢叫做內嵌視圖,它產生了1..49這些數,我們通過DBMS_RANDOM.VALUE,  
//來對這49個數進行排序。我們將結果集打包在另一個內嵌視圖中只返回6行,  
//如果我們反覆的執行這個查詢,我們每次得到的6個數都會不同。  
--  
//這種問題經常出現,或許不是關於怎麼產生6個隨機數,而是怎麼樣得到N行?  
//例如,我們想要得到包括在2011-05-01和2011-05-15之間的所有日期;怎樣不用"真實"表,  
//解決這個問題呢?Oracle9i/10g內建的PIPELINED function將會告訴你答案。  
//我們編寫一個PL/SQL函數,它工作起來就像一個表。我們需要藉助於sql的集合類型,  
//它描述了PIPELINED function返回的值。這個例子中,我們選擇了一個數的表,我們建立的虛擬表,  
//它將會返回下面的數:1,2,3,...N :  
create type array  
    as table of number;  
/  
//下一步,我們建立這個PIPELINED function,它將會接收一個輸入來限制返回的行數。如果沒有輸入,  
//這個函數將會一直長時間的產生很多行(所以,在這個查詢中,一定要細心,確保使用rownum,  
//或其他的數來限制產生的行數)。  
//位於第4行的PIPELINED關鍵字,將會使這個函數工作起來想像一個表:  
create function  
  gen_numbers(n in number default null)  
  return array  
  PIPELINED  
  as 
  begin  
     for i in 1 .. nvl(n,999999999)  
     loop  
         pipe row(i);  
     end loop;  
     return;  
  end;  
/  
//假設我們需要3行資料,我們現在可以使用下面的其中一個查詢實現:  
select * from TABLE(gen_numbers(3));  
COLUMN_VALUE  
------------  
           1  
           2  
           3  
or  
select * from TABLE(gen_numbers)  
where rownum <= 3;  
COLUMN_VALUE  
------------  
           1  
           2  
           3  
//現在我們準備去回答最開始的問題了,語句如下:  
select *  
  from (  
  select *  
    from (select * from table(gen_numbers(49)))  
  order by dbms_random.random  
  )  
where rownum <= 6  
/  
COLUMN_VALUE  
------------  
          27  
          24  
          46  
          17  
          44  
          45  
//我們可以使用這個虛擬表的功能去做很多事情,例如產生一個範圍內的所有日期:  
select to_date('2011-05-01','yyyy-mm-dd')+  
        column_value-1  
  from TABLE(gen_numbers(15))  
/  
TO_DATE('2' 
-----------  
2011-05-01   
2011-05-02   
2011-05-03   
2011-05-04   
2011-05-05   
2011-05-06   
2011-05-07   
2011-05-08   
2011-05-09   
2011-05-10   
2011-05-11   
2011-05-12   
2011-05-13   
2011-05-14   
2011-05-15   
//注意上面我們使用了column_value,這是一個PIPELINED function返回的預設列的名字。  
//典型的Pipelined例子  
//當使用PL/SQL表函數時,下面是典型的步驟  
//  ·生產函數必須在其定義中使用PIPELINED關鍵字  
//  ·生產函數必須使用一個out參數,這個參數是一個集合,對應到返回的結果集  
//  ·一旦有結果產生,通過使用PIPE ROW關鍵字將其輸送給消費函數  
//  ·生產函數必須以RETURN語句結束,但是不需要制定傳回值  
//  ·消費函數必須使用TABLE關鍵字,將從PIPELINE function返回的行集當成一個常規表  
//第一步.定義一個返回的行集的格式。  
//       在這個執行個體中,我們返回這三個類型的值:int,date,varchar2(25)  
CREATE OR REPLACE TYPE myObjectFormat   
AS OBJECT  
(  
  A   INT,  
  B   DATE,  
  C   VARCHAR2(25)  
)  
/  
//下一步,為第一步定義的類型定義一個集合類型  
CREATE OR REPLACE TYPE myTableType  
   AS TABLE OF myObjectFormat  
/  
//最後,生產函數被打包到一個包裡面,它是一個pipelined function就像被pipelined關鍵字所標記一樣。  
CREATE OR REPLACE PACKAGE myDemoPack  
AS  
      FUNCTION prodFunc RETURN myTableType PIPELINED;  
END;  
/  
CREATE OR REPLACE PACKAGE BODY myDemoPack AS  
FUNCTION prodFunc RETURN myTableType PIPELINED IS  
BEGIN  
  FOR i in 1 .. 5  
    LOOP  
      PIPE ROW (myObjectFormat(i,SYSDATE+i,'Row '||i));  
    END LOOP;  
    RETURN;  
  END;  
END;  
/  
//測試結果:  
alter session set nls_date_format='yyyy-mm-dd';  
SELECT * FROM TABLE(myDemoPack.prodFunc());  
                A B           C  
----------------- ----------- ------------  
                1 2011-05-05  Row 1  
                2 2011-05-06  Row 2  
                3 2011-05-07  Row 3  
                4 2011-05-08  Row 4  
                5 2011-05-09  Row 5  
//結論:  
//在一個select語句裡面,我們需要一個資料來源,而不是一張表的話,Pipelined functions非常有用。 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.