Oracle之數組


[Oracle整理]Oracle之數組

說明:本內容是工作用到的知識點整理,來自工作中和網絡。
代碼於Oracle9上測試。

 

Oracle數組一般可以分為固定數組和可變數組

集合:是具有相同定義的元素的聚合。Oracle有兩種類型的集合:

可變長數組(VARRAY):可以有任意數量的元素,但必須預先定義限制值。

嵌套表:視為表中之表,可以有任意數量的元素,不需要預先定義限制值。

在PL/SQL中是沒有數組(Array)概念的。但是如果程序員想用Array的話,就得變通一下,用TYPE   和Table   of   Record來代替多維數組,一樣挺好用的。

固定數組

-- ============ char array ===============
DECLARE
  -- declare fixed array
  TYPE arry_var IS VARRAY(2) OF VARCHAR2(10);
  arry_name arry_var;
BEGIN
  -- init array
  arry_name := arry_var('tom', 'jim','tim');

  dbms_output.put_line(arry_name(1));
  dbms_output.put_line(arry_name(2));
END;
-- ================ number array ========
DECLARE
  -- declare fixed array
  TYPE arry_num IS VARRAY(10) OF NUMBER;
  arry_top arry_num;
BEGIN
  -- init array
  arry_top := arry_num(1,2,3);

  dbms_output.put_line(arry_top(1));
  dbms_output.put_line(arry_top(2));
END;

1 VARRAY(10)變數數組大小為10

2OF NUMBER 表示數值類型是number

可變數組

一維數組

DECLARE
  TYPE t_table IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;
  v_table t_table;
  v_cnt   NUMBER;
BEGIN
  v_table(1) := '1';
  v_table(2) := '3';
  v_table(3) := '9';

  v_cnt := v_table.COUNT;
  FOR i IN 1 .. v_cnt LOOP
    dbms_output.put_line(v_table(i));
    END LOOP;
END;

多維數組

1 Create Table

create table XXUSER
(
  USER_ID   NUMBER,
  USER_NAME VARCHAR2(255),
  SEX       VARCHAR2(2),
  AGE       NUMBER(3),
  ADDRESS   VARCHAR2(2000)
)

2 定義結果集(Record)

存放xxuser的部分字段

DECLARE
  -- only 2 fileds
  TYPE t_record_user IS RECORD(
    user_id   xxuser.user_id%type,
    user_name xxuser.user_name%type);

  TYPE t_user IS TABLE OF t_record_user INDEX BY BINARY_INTEGER;

  v_arry_user t_user;
BEGIN
  SELECT user_id, user_name BULK COLLECT INTO v_arry_user FROM xxuser;
  FOR i IN 1 .. v_arry_user.COUNT LOOP
    dbms_output.put_line(v_arry_user(i).user_name);
  END LOOP;
END;

3 使用ROWTYPE

存放xxuser的全部字段,比Record簡潔。

DECLARE
  -- ALL,XXUser(user_id, user_name, sex, age, address)
  TYPE t_user IS TABLE OF xxuser%ROWTYPE INDEX BY BINARY_INTEGER;

  v_arry_user t_user;
BEGIN
  SELECT * BULK COLLECT INTO v_arry_user FROM xxuser;
  FOR i IN 1 .. v_arry_user.COUNT LOOP
    dbms_output.put_line(v_arry_user(i).user_name || v_arry_user(i).sex);
  END LOOP;
END;

 

 

==================================================

 

 

 

 

對於集合類型,與單一的數據類型相比較而言,應該以一個整體的觀念來考慮集合,即是一批類型相同的數據組合而非單一的數據。因此集
合類型集合的聲明、賦值、初始化較之單一類型而言,有很大的不同。尤其是嵌套表與變長數組,在賦值之前必須先初始化。當嵌套表和變長數
組在聲明時,它們都會自動地被設置成NULL值。也就是嵌套表和變長數組中集合不存在任何元素,並不是針對它所擁有的元素。可以使用系統定
義的與集合類型同名的函數來初始化集合。我們必須顯式地調用構造函數為每一個變長數組和嵌套表變量進行初始化操作(對於關聯數組來說,
是不需要使用構造函數進行初始化的)。

        有關集合類型的描述請參考:
        PL/SQL 聯合數組與嵌套表 
        PL/SQL 變長數組
        PL/SQL --> PL/SQL記錄 

一、聯合數組的賦值

    聯合數組的不需要初始化,直接賦值即可。(后續講到的集合的初始化均指嵌套表與變長數組)

 

  1. DECLARE    
  2.    TYPE idx_loc_type IS TABLE OF VARCHAR2( 13 )    
  3.                            INDEX BY BINARY_INTEGER;    
  4.     
  5.    loc_tab   idx_loc_type;    
  6. BEGIN    
  7.    loc_tab( 1 ) := 'NEW YORK';                        -->聯合數組不需要初始化,直接賦值即可    
  8.    loc_tab( 2 ) := 'DALLAS';    
  9.    DBMS_OUTPUT.put_line( ' loc_tab(1) value is ' || loc_tab( 1 ) );    
  10.    DBMS_OUTPUT.put_line( ' loc_tab(2) value is ' || loc_tab( 2 ) );    
  11. END;    
  12.     
  13. --------------------------------------------------------------------------------------------------------     
  14.     
  15. DECLARE    
  16.    TYPE idx_loc_type IS TABLE OF VARCHAR2( 13 )    
  17.                            INDEX BY BINARY_INTEGER;    
  18.     
  19.    loc_tab     idx_loc_type;    
  20.    v_counter   INTEGER := 0;    
  21. BEGIN    
  22.    FOR x IN ( SELECT loc FROM dept )       -->這里通過for 循環得到loc的值    
  23.    LOOP    
  24.       v_counter   := v_counter + 1;        -->使用一個v_counter變量來控制聯合數組的下標    
  25.       loc_tab( v_counter ) := x.loc;       -->將得到的loc的值賦值給聯合數組中對應的一個下標位    
  26.       DBMS_OUTPUT.put_line( ' loc_tab(' || v_counter || ') value is ' || loc_tab( v_counter ) );    
  27.    END LOOP;    
  28. END;  


二、集合的初始化與賦值

1、初始化的方法
     集合類型主要分為三步來完成,一是聲明,二是初始化,三是賦值。初始化和賦值可以在聲明塊中完成,也可以在執行塊中完成。
        collection_name collection_type:=collection_type();   -->初始化集合為空(empty)
        
     集合的初始化主要是通過構造函數(構造函數即是聲明類型是的類型名)來進行初始化,下面常用的初始化方法包括:
        a、在聲明塊聲明集合,且在聲明塊中使用構造函數初始化為空(empty)但非NULL,在執行塊中使用extend方式后進行賦值
        b、在聲明塊聲明集合,在執行塊中使用構造函數初始化為空(empty)但非NULL,在執行塊中使用extend方式后賦值
        c、在聲明塊聲明集合,在執行塊中使用構造函數初始化時一並賦值
        d、在聲明塊聲明集合,同時使用構造函數初始化並賦值,即三步合為一步來完成
     對於初始化為空的集合(empty),后續需要使用extend方式來擴展容量,除非使用bulk collect into方式
             
2、集合賦值的方法
        collection_name(subscript) := expression;
        
3、賦值時可能引起的異常 
     在下面幾種給集合元素賦值的情況下,可能會引起多種異常。
        a、如果下標索引不存在或無法轉換成正確的數據類型,PL/SQL就會拋出預定義異常VALUE_ERROR。
                通常,下標是一個整數。但關聯數組的下標也可以是VARCHAR2類型。 
        b、如果所給下標索引指向了一個未初始化的元素時,PL/SQL就會拋出SUBSCRIPT_BEYOND_COUNT異常。 
        c、如果集合被自動初始化為空值並且程序引用了其中的一個元素,PL/SQL會拋出COLLECTION_IS_NULL異常。

4、元素的引用
        collection_name(subscript)

     可以把其中的表元素作為參數傳遞。如verify_loc(nest_loc_tab(i)),verify_loc為函數或過程。

   

三、集合的初始化與賦值引用示例    

 

  1. 1、未初始化集合的情形    
  2. DECLARE    
  3.    TYPE nest_loc_type IS TABLE OF VARCHAR2( 13 );    
  4.     
  5.    loc_tab   nest_loc_type;    
  6. BEGIN    
  7.    loc_tab( 1 ) := 'NEW YORK';    
  8.    loc_tab( 2 ) := 'DALLAS';    
  9.    DBMS_OUTPUT.put_line( ' loc_tab(1) value is ' || loc_tab( 1 ) );    
  10.    DBMS_OUTPUT.put_line( ' loc_tab(2) value is ' || loc_tab( 2 ) );    
  11. END;    
  12.     
  13. DECLARE    
  14. *    
  15. ERROR at line 1:    
  16. ora-06531: Reference to uninitialized collection  -->收到了ora-06531錯誤提示,變長數組未初始化時會收到同樣的錯誤提示    
  17. ora-06512: at line 6    
  18. --------------------------------------------------------------------------------------------------------    
  19.     
  20. 2、集合為NULL的判斷    
  21. DECLARE    
  22.    TYPE nest_loc_type IS TABLE OF VARCHAR2( 13 );    
  23.     
  24.    loc_tab   nest_loc_type;    
  25. BEGIN    
  26.    IF loc_tab IS NULL THEN    
  27.       DBMS_OUTPUT.put_line( 'Before initialization, the loc_tab is null.' );    
  28.    -- While the collection  is null, we cannot check its COUNT attribute.    
  29.    --   DBMS_OUTPUT.PUT_LINE('It has ' || loc_tab.COUNT || ' elements.');    
  30.    ELSE    
  31.       DBMS_OUTPUT.put_line( 'Before initialization, the loc_tab is not null.' );    
  32.    END IF;    
  33.     
  34.    loc_tab     := nest_loc_type( );         --> initialize empty nest table    
  35.     
  36.    IF loc_tab IS NULL THEN    
  37.       DBMS_OUTPUT.put_line( 'After initialization, the loc_tab is null.' );    
  38.    ELSE    
  39.       DBMS_OUTPUT.put_line( 'After initialization, the loc_tab is not null.' );    
  40.       DBMS_OUTPUT.put_line( 'It has ' || loc_tab.COUNT || ' elements.' );    
  41.    END IF;    
  42. END;    
  43.     
  44. Before initialization, the loc_tab is null.    
  45. After initialization, the loc_tab is not null.    
  46. It has 0 elements.    
  47.     
  48. PL/SQL procedure successfully completed.    
  49. --------------------------------------------------------------------------------------------------------    
  50.     
  51. 3、使用空構造函數在聲明時進行初始化    
  52. -->使用該方法初始化之后,表明嵌套表或變成數組是空的,但是非NULL,在執行塊再對其賦值    
  53. -->下面對變長數組進行初始化    
  54. DECLARE    
  55.    TYPE varry_loc_type IS VARRAY( 10 ) OF scott.dept.loc%TYPE;    
  56.     
  57.    varry_loc_tab   varry_loc_type := varry_loc_type( );                 -->僅僅是在集合變量之后使用空構造函數    
  58. BEGIN    
  59.    varry_loc_tab( 1 ) := 'NEW YORK';                                    -->盡管變長數組被初始化,但仍然不能直接賦值            
  60.    varry_loc_tab( 2 ) := 'DALLAS';                                      -->這是由變長數組和嵌套表特性決定需要先做extend       
  61.    DBMS_OUTPUT.put_line( ' varry_loc_tab(1) value is ' || varry_loc_tab( 1 ) );    
  62.    DBMS_OUTPUT.put_line( ' varry_loc_tab(2) value is ' || varry_loc_tab( 2 ) );    
  63. END;    
  64.     
  65. DECLARE    
  66. *    
  67. ERROR at line 1:    
  68. ora-06533: subscript beyond count    
  69. ora-06512: at line 6    
  70. --------------------------------------------------------------------------------------------------------    
  71.     
  72. 4、使用空構造函數在聲明時進行初始化,執行塊使用extend方式擴展后賦值    
  73. DECLARE    
  74.    TYPE varry_loc_type IS VARRAY( 10 ) OF scott.dept.loc%TYPE;    
  75.     
  76.    varry_loc_tab   varry_loc_type := varry_loc_type( );              -->僅僅是在集合變量之后使用空構造函數    
  77. BEGIN    
  78.    varry_loc_tab.EXTEND;                                             -->需要使用extend方式擴展集合容量    
  79.    varry_loc_tab( 1 ) := 'NEW YORK';    
  80.    varry_loc_tab.EXTEND;                                             -->需要使用extend方式擴展集合容量    
  81.    varry_loc_tab( 2 ) := 'DALLAS';    
  82.    DBMS_OUTPUT.put_line( ' varry_loc_tab(1) value is ' || varry_loc_tab( 1 ) );    
  83.    DBMS_OUTPUT.put_line( ' varry_loc_tab(2) value is ' || varry_loc_tab( 2 ) );    
  84. END;    
  85. --------------------------------------------------------------------------------------------------------    
  86.     
  87. 5、嵌套表的初始化,使用構造函數在執行塊直接初始化並賦值    
  88. DECLARE    
  89.    TYPE nest_loc_type IS TABLE OF VARCHAR2( 13 );    
  90.     
  91.    loc_tab   nest_loc_type;    
  92. BEGIN    
  93.    loc_tab     :=    
  94.       nest_loc_type( 'NEW YORK'           -->使用聲明時的類型nest_loc_type函數來進行初始化    
  95.                     ,'DALLAS'    
  96.                     ,'CHICAGO'    
  97.                     ,'BOSTON' );    
  98.     
  99.    FOR i IN 1 .. loc_tab.COUNT    
  100.    LOOP    
  101.       DBMS_OUTPUT.put_line( 'loc_tab(' || i || ') value is ' || loc_tab( i ) );    
  102.    END LOOP;    
  103. END;    
  104. --------------------------------------------------------------------------------------------------------    
  105.     
  106. 6、含有NOT NULL嵌套表的初始化    
  107. DECLARE    
  108.    TYPE loc_type IS TABLE OF VARCHAR2( 13 ) NOT NULL;      -->定義了NOT NULL約束條件    
  109.     
  110.    loc_tab   loc_type;    
  111. BEGIN    
  112.    loc_tab     :=    
  113.       loc_type( 'NEW york'    
  114.                ,NULL                                       -->構造時傳遞了NULL值    
  115.                ,NULL    
  116.                ,'boston' );    
  117.     
  118.    FOR i IN 1 .. loc_tab.COUNT    
  119.    LOOP    
  120.       DBMS_OUTPUT.put_line( 'loc_tab(' || i || ') value is ' || loc_tab( i ) );    
  121.    END LOOP;    
  122. END;    
  123.     
  124. -->由於存在not null約束,初始化傳遞null值則收到錯誤提示    
  125. ERROR at line 8:    
  126. ora-06550: line 8, column 17:    
  127. pls-00567: cannot pass NULL to a NOT NULL constrained formal parameter    
  128. ora-06550: line 9, column 17:    
  129. pls-00567: cannot pass NULL to a NOT NULL constrained formal parameter    
  130. ora-06550: line 6, column 4:    
  131. pl/SQL: Statement ignored    
  132. --------------------------------------------------------------------------------------------------------    
  133.     
  134. 7、變長數組的初始化,使用構造函數直接初始化並賦值    
  135. -->變長數組的初始化與嵌套表一樣,可以使用構造函數直接初始化並賦值    
  136. DECLARE    
  137.    TYPE varry_loc_type IS VARRAY( 10 ) OF scott.dept.loc%TYPE;    
  138.     
  139.    varry_loc_tab   varry_loc_type;    
  140. BEGIN    
  141.    varry_loc_tab :=    
  142.       varry_loc_type( 'NEW YORK'    
  143.                      ,'DALLAS'    
  144.                      ,'CHICAGO'    
  145.                      ,'BOSTON' );    
  146.     
  147.    FOR i IN varry_loc_tab.FIRST .. varry_loc_tab.LAST   -->注意此處使用了集合方法中的函數first和last來控制循環步長    
  148.    LOOP    
  149.       DBMS_OUTPUT.put_line( 'varry_loc_tab(' || i || ') value is ' || varry_loc_tab( i ) );    
  150.    END LOOP;    
  151. END;    
  152. --------------------------------------------------------------------------------------------------------    
  153.     
  154. 8、聲明時初始化(構造)、並賦值    
  155. DECLARE    
  156.    TYPE nest_loc_type IS TABLE OF VARCHAR2( 13 ) NOT NULL;    
  157.     
  158.    nest_loc_tab   nest_loc_type := nest_loc_type( 'NEW YORK', 'DALLAS', 'CHICAGO' ); -->在聲明時直接初始化並賦值    
  159. BEGIN    
  160.    FOR i IN 1 .. nest_loc_tab.COUNT    -->注意此處調用了集合操作方法中的count函數    
  161.    LOOP    
  162.       DBMS_OUTPUT.put_line( 'nest_loc_tab(' || i || ') value is ' || nest_loc_tab( i ) );    
  163.    END LOOP;    
  164. END;    
  165. --------------------------------------------------------------------------------------------------------    
  166.     
  167. 9、SQL語句中使用構造函數    
  168. CREATE OR REPLACE TYPE mail_type IS TABLE OF VARCHAR2( 100 );   -->創建一個嵌套表類型    
  169.     
  170. CREATE TABLE tb_tmp                   -->創建表tb_tmp    
  171. (    
  172.    empno   NUMBER( 4 )    
  173.   ,ename   VARCHAR2( 10 )    
  174.   ,mail    mail_type                  -->列mail的類型為mail_type    
  175. )    
  176. NESTED TABLE mail                     -->注意此處需要指定嵌套表的存儲方式    
  177.    STORE AS mail_tab;    
  178.     
  179. INSERT INTO tb_tmp    
  180.    SELECT 8888, 'Jack', mail_type( 'Jack@yahoo.com', 'Jack@163.com' ) FROM dual;  -->插入數據時需要使用構造函數    
  181.     
  182. 10、集合與集合之間的賦值    
  183. -->下面的例子聲明了兩個變長數組last_name_type和surname_type    
  184. DECLARE    
  185.    TYPE last_name_type IS VARRAY( 3 ) OF VARCHAR2( 64 );    
  186.     
  187.    TYPE surname_type IS VARRAY( 3 ) OF VARCHAR2( 64 );    
  188.     
  189.    -->下面聲明了兩個相同類型的變長數組並為其賦值,group1和group2使用了相同的構造函數    
  190.    group1   last_name_type := last_name_type( 'Jones', 'Wong', 'Marceau' );    
  191.    group2   last_name_type := last_name_type( 'Klein', 'Patsos', 'Singh' );    
  192.    -->下面的group3使用了surname_type作為類型    
  193.    group3   surname_type := surname_type( 'Trevisi', 'Macleod', 'Marquez' );    
  194. BEGIN    
  195.    group1      := group2;                           -- >group1 和group2之間可以相互賦值    
  196. --   group3 := group2;                             -->raises an error    PLS-00382: expression is of wrong type    
  197. END;    
  198. -- >group3和group2則不能賦值,因為兩者為不同的數據類型    
  199. -->盡管last_name_type與surname_type類型定義是相同的,但其實例化后,其集合變量不能互相賦值    
  200. --------------------------------------------------------------------------------------------------------    
  201.     
  202. 11、使用NULL值集合為集合賦值    
  203. DECLARE    
  204.    TYPE nest_loc_type IS TABLE OF VARCHAR2( 30 );    
  205.     
  206.    nest_loc_tab         nest_loc_type := nest_loc_type( 'NEW YORK', 'DALLAS', 'CHICAGO' );    
  207.    empty_nest_loc_tab   nest_loc_type;                --> 嵌套表empty_nest_loc_tab沒有初始化,此時被自動置為NULL    
  208. BEGIN    
  209.    IF nest_loc_tab IS NOT NULL THEN    
  210.       DBMS_OUTPUT.put_line( 'OK, at first nest_loc_tab is not null.' );    
  211.    END IF;    
  212.     
  213.    nest_loc_tab := empty_nest_loc_tab;                -->將empty_nest_loc_tab的值(NULL)嵌套表賦值給nest_loc_tab    
  214.     
  215.    IF nest_loc_tab IS NULL THEN                       --> 此時nest_loc_tab被置為NULL,相當於沒有初始化    
  216.       DBMS_OUTPUT.put_line( 'OK, now nest_loc_tab has become null.' );    
  217.    END IF;    
  218.     
  219.    nest_loc_tab := nest_loc_type( 'NEW YORK', 'DALLAS', 'CHICAGO' );  -->此時如果后續需要使用該嵌套表,應重新初始化它    
  220. END;    
  221.     
  222. 12、記錄類型的變長數組的初始化、賦值與元素引用    
  223. DECLARE    
  224.    TYPE emp_name_rec IS RECORD                             -->聲明一個基於用戶定義的記錄類型    
  225.    (    
  226.       firstname   employees.first_name%TYPE    
  227.      ,lastname    employees.last_name%TYPE    
  228.      ,hiredate    employees.hire_date%TYPE    
  229.    );    
  230.     
  231.    TYPE emplist_arr IS VARRAY( 10 ) OF emp_name_rec;       -->聲明一個基於記錄的變長數組,且最大尺寸為10    
  232.     
  233.    seniorsalespeople   emplist_arr;                        -->聲明基於記錄的變長數組變量    
  234.     
  235.    CURSOR c1 IS                                            -->聲明游標,其列前面的記錄類型相對照    
  236.       SELECT first_name, last_name, hire_date FROM employees;    
  237.     
  238.    TYPE nameset IS TABLE OF c1%ROWTYPE;                    -->聲明基於游標的記錄類型    
  239.     
  240.    seniorten           nameset;                            -->聲明基於游標記錄類型的變量    
  241.    endcounter          NUMBER := 10;                       -->變量endcounter計數器    
  242. BEGIN    
  243.    seniorsalespeople := emplist_arr( );                    -->初始化集合    
  244.     
  245.    SELECT first_name, last_name, hire_date                 -->從表中提取數據,且使用了BULK COLLECT INTO方式    
  246.    BULK   COLLECT INTO seniorten    
  247.    FROM   employees    
  248.    WHERE  job_id = 'SA_REP'    
  249.    ORDER BY hire_date;    
  250.     
  251.    IF seniorten.LAST > 0 THEN    
  252.       IF seniorten.LAST < 10 THEN                          -->如果小於10,則縮小變長數組的最大尺寸    
  253.          endcounter  := seniorten.LAST;    
  254.       END IF;    
  255.     
  256.       FOR i IN 1 .. endcounter     -->使用循環將游標類型變量中的元素逐條賦值給記錄的變長數組變量seniorsalespeople並輸出    
  257.       LOOP    
  258.          seniorsalespeople.EXTEND( 1 );    
  259.          seniorsalespeople( i ) := seniorten( i );    
  260.          DBMS_OUTPUT.    
  261.          put_line(seniorsalespeople(i).lastname||', '||seniorsalespeople(i).firstname||', '||seniorsalespeople(i).hiredate);    
  262.       END LOOP;    
  263.    END IF;    
  264. END;    
  265.     
  266.     上面的這個例子是一復合的數據類型,比單一的集合類型更為復雜。我們知道集合通常是針對單列多行數據而言,而記錄則是單行多列。兩    
  267. 者的綜合,則此時就等同於數據庫中的一張二維表。示例中首先聲明用戶定義的記錄類型以及變長數組,接下來基於這兩者聲明變量。后面使用    
  268. 基於游標的記錄類型來申明變量seniorten與前面的變量seniorsalespeople相對應,seniorten變量用於存儲后面的SQL語句批量提取的數據集。    
  269. 后面使用了一個for循環來從seniorten變量取出數據並賦值為seniorsalespeople。注:在這個例子中變量seniorten存儲的記錄超出了變長數組    
  270. 的最大尺寸,因此后續的被丟棄。    
  271.     
  272. 13、記錄類型的嵌套表的初始化、賦值與元素引用    
  273. DECLARE    
  274.    TYPE emp_name_rec IS RECORD    
  275.    (    
  276.       firstname   employees.first_name%TYPE    
  277.      ,lastname    employees.last_name%TYPE    
  278.      ,hiredate    employees.hire_date%TYPE    
  279.    );    
  280.     
  281.    TYPE emplist_tab IS TABLE OF emp_name_rec;    
  282.     
  283.    seniorsalespeople   emplist_tab;    
  284.    endcounter          NUMBER := 10;    
  285.     
  286.    TYPE empcurtyp IS REF CURSOR;    -->聲明游標變量類型     
  287.     
  288.    emp_cv              empcurtyp;   -->聲明游標變量類型的變量emp_cv    
  289. BEGIN    
  290.    OPEN emp_cv FOR    
  291.       SELECT first_name, last_name, hire_date    
  292.       FROM   employees    
  293.       WHERE  job_id = 'SA_REP'    
  294.       ORDER BY hire_date;    
  295.     
  296.    FETCH emp_cv    
  297.    BULK   COLLECT INTO seniorsalespeople;    -->使用BULK   COLLECT INTO 方式一次將數據加載到seniorsalespeople變量    
  298.     
  299.    CLOSE emp_cv;    
  300.     
  301.    IF seniorsalespeople.LAST > 0 THEN    
  302.       IF seniorsalespeople.LAST < 10 THEN    
  303.          endcounter  := seniorsalespeople.LAST;    
  304.       END IF;    
  305.     
  306.       FOR i IN 1 .. endcounter    
  307.       LOOP    
  308.          DBMS_OUTPUT.    
  309.          put_line(seniorsalespeople(i).lastname||', '||seniorsalespeople(i).firstname||', '||seniorsalespeople(i).hiredate);    
  310.       END LOOP;    
  311.    END IF;    
  312. END;    
  313. -->Author : Robinson Cheng    
  314. -->Blog   : http://blog.csdn.net/robinson_0612    
  315.     
  316.     上面的這個例子稍有不同於前面的例子,使用的基於用戶定義記錄的嵌套表方式,且使用了游標變量類型。在fetch時直接將數據fetch 到    
  317. 集合變量seniorsalespeople中,此時不需要使用extend方式來擴展。     


四、總結

1、對於集合類型在為其賦值之前,需要對集合進行初始化。而聯合數組不需要初始化而直接進行賦值。
2、在聲明嵌套表與變長數組時,這些集合類型會被自動置為NULL,即集合不存在任何元素。而不是集合中的元素為NULL。
3、集合類型的初始化方法是是直接使用聲明時的同名類型構造器來對集合進行初始化。
4、集合類型的初始化方法有多種,可以在聲明時初始化,也可以在執行塊初始化。
5、集合類型的賦值可以在聲明塊聲明時賦值,也可以在執行塊執行時使用extend方式擴展后再賦值。
6、集合類型的初始化過程連同賦值可以在聲明集合的同時使用構造函數直接進行初始化並賦值,從而一步完成。
7、SQL語句中也需要使用構造函數來操作集合數據。
8、注意本文描述中的集合初始化后為空的理解。初始化后為空表示的是一個空(empty)集合,而未初始化時是NULL(UNKNOWN)值。
9、集合與集合之間的賦值需要聲明的為同一類型的變量之間才可以賦值,否則收到錯誤提示。

10、注意理解復合類型之間(嵌套表和變長數組中嵌有PL/SQL記錄)的變量元素間的傳遞以及集合方法BULK COLLECT INTO,LAST,EXTEND等。


--==========================================================================================


 

Oracle集合(聯合數組(索引表),嵌套表,變長數組,記錄類型的嵌套表)的初始化與賦值,以及它們的區別
 
--其中嵌套表與變長數組在賦值之前必須初始化,可以使用與集合類型同名的函數來進行初始化,
聯合數組無需初始化  www.2cto.com  
 
--1.聯合數組:
DECLARE  
  TYPE ind_tab_type IS TABLE OF VARCHAR2(2000)  
                    INDEX BY BINARY_INTEGER;  
  ind_tab           ind_tab_type;  
BEGIN  
  ind_tab(1) := 'lubinsu';--這里的下標可以隨意指定,可以通過循環來獲取  
  ind_tab(2) := 'luzhou';  
  --dbms_output.put_line(ind_tab(0));  
  --dbms_output.put_line(ind_tab(1));  
  FOR i IN ind_tab.first..ind_tab.last LOOP  
    dbms_output.put_line('ind_tab(' || i || '):' || ind_tab(i));  
  END LOOP;  
END;  
/  
 
--2.嵌套表的初始化1
--嵌套表的下標默認為1開始,也可以自己指定任意值  www.2cto.com  
DECLARE  
  TYPE nest_tab_type IS TABLE OF VARCHAR2(2000) NOT NULL; --如果設置not null條件那么在初始化的時候不可以設置null  
  nest_tab nest_tab_type := nest_tab_type('lubinsu', 'luzhou'); --初始化的時候只要在集合變量之后使用空的構造函數或者直接賦值即可  
BEGIN  
  FOR i IN nest_tab.first .. nest_tab.last LOOP  
    dbms_output.put_line('nest_tab(' || i || ') value is ' || nest_tab(i));  
  END LOOP;  
END;  
/  
 
--3.嵌套表和的初始化2
DECLARE  
  TYPE nest_tab_type IS TABLE OF VARCHAR2(2000) NOT NULL; --如果設置not null條件那么在初始化的時候不可以設置null  
  nest_tab nest_tab_type := nest_tab_type(); --初始化的時候只要在集合變量之后使用空的構造函數或者直接賦值即可  
BEGIN  
  nest_tab.extend;  
  nest_tab(1) := 'lubinsu';  
  nest_tab.extend;  
  nest_tab(2) := 'luzhou';  
  FOR i IN nest_tab.first .. nest_tab.last LOOP  
    dbms_output.put_line('nest_tab(' || i || '):' || nest_tab(i));  
  END LOOP;  
END;  
/  
--如果設置not null條件那么在初始化的時候不可以設置null,如:nest_tab(1) := null;否則出錯提示;  
ORA-06550: line 7, column 18:  
PLS-00382: expression is of wrong type  
ORA-06550: line 7, column 3:  
PL/SQL: Statement ignored  
--賦值的時候必須使用extend來擴展集合的容量否則會如下錯誤  
ERROR at line 1:    
ora-06533: subscript beyond count    
ora-06512: at line 6  
/  
 
--4.變長數組類似於PL/SQL表,每個元素都被分配了一個連續的下標,從1開始
--4.變長數組的初始化(與嵌套表的初始化方式一樣)
DECLARE  
  TYPE varray_tab_type IS VARRAY(10) OF VARCHAR2(2000);  
  varray_tab varray_tab_type :=  varray_tab_type('lubinsu', 'luzhou'); --初始化的時候只要在集合變量之后使用空的構造函數或者直接賦值即可  
BEGIN  
  varray_tab.extend;  
  varray_tab(3) := 'zengq';  
  varray_tab.extend;  
  varray_tab(4) := 'buwei';  
  FOR i IN varray_tab.first .. varray_tab.last LOOP  
    dbms_output.put_line('varray_tab(' || i || '):' || varray_tab(i));  
  END LOOP;  
END;  
/  
 
--5.集合與集合之間的賦值必須是相同的TYPE
DECLARE  
  TYPE type1 IS TABLE OF NUMBER(2);  
  TYPE type2 IS TABLE OF NUMBER(2);  
  type1_tab  type1 := type1(1, 2, 3);  
  type1_tab2 type1 := type1(4, 5, 6);  
  type2_tab  type2 := type2(3, 2, 1);  
BEGIN  
  type1_tab2 := type1_tab;  
  --type1_tab2 := type2_tab; 不可用  
  FOR i IN type1_tab2.first .. type1_tab2.last LOOP  
    dbms_output.put_line('type1_tab2(' || i || '):' || type1_tab2(i));  
  END LOOP;  
END;  
/  
--type1_tab2 := type2_tab;報錯  
ORA-06550: line 10, column 17:  
PLS-00382: expression is of wrong type  
ORA-06550: line 10, column 3:  
PL/SQL: Statement ignored  
  
RESULT:  
type1_tab2(1):1  
type1_tab2(2):2  
type1_tab2(3):3  
/  
 
--6.使用null值為集合賦值
DECLARE  
  TYPE type1 IS TABLE OF NUMBER(2);  
  type1_tab  type1 := type1();--已經初始化,不為空,雖然沒有賦值  
  type1_tab2 type1;--未初始化,為空  
BEGIN  
  IF type1_tab IS NOT NULL THEN  
    dbms_output.put_line('type1_tab is not null');  
  END IF;  
    
  --type1_tab := NULL;  
  --或者  
  type1_tab := type1_tab2;  
    
  IF type1_tab IS NULL THEN  
    dbms_output.put_line('type1_tab is null');  
  END IF;  
END;  
/  
 
--7.超出變長數組長度的值將會被丟棄  www.2cto.com  
--8.記錄類型的嵌套表的初始化,賦值以及元素的引用
DECLARE  
  TYPE object_rec IS RECORD(  
    object_id   all_objects_loc.object_id%TYPE,  
    object_name all_objects_loc.object_name%TYPE,  
    object_type all_objects_loc.object_type%TYPE);  
  
  TYPE object_tab_type IS TABLE OF object_rec;  
  
  object_tab object_tab_type;  
  
  TYPE obj_cur_type IS REF CURSOR; --聲明游標變量類型  
  obj_cur obj_cur_type;  
BEGIN  
  OPEN obj_cur FOR  
    SELECT a.object_id, a.object_name, a.object_type  
    FROM   all_objects_loc a  
    WHERE  rownum <= 10;  
  
  FETCH obj_cur BULK COLLECT  
    INTO object_tab;  
  CLOSE obj_cur;  
  FOR i IN 1 .. object_tab.count LOOP  
    dbms_output.put_line('object_tab(' || i || '):' || object_tab(i)  
                         .object_id || ',' || object_tab(i).object_name || ',' || object_tab(i)  
                         .object_type);  
  END LOOP;  
END;  
/  

原文:http://blog.csdn.net/leshami/article/details/7525891

原文:http://www.2cto.com/database/201301/184529.html

 

 

 

=========================================================================================================

 

 

個人理解,table函數是把數組類型的變量展開顯示出來

三種用法:

 1 table()與返回值為數組的類型的普通函數一起使用

 2 table()與返回值為數組類型的管道函數一起使用

3, table()與系統包中的管道函數一起使用 實際也就是2

 

以下代碼為例子:

 

[c-sharp] view plain copy
  1. --創建類型t_test  
  2. SQL> create or replace type t_test as object (  
  3.   2  id number,  
  4.   3  time date,  
  5.   4  data varchar2(60)  
  6.   5  );  
  7.   6  /  
  8.    
  9. Type created  
  10.    
  11. Executed in 0.063 seconds  
  12.  --創建以t_test類型的數組t_test_tb  
  13. SQL> create or replace type t_test_tb as table of t_test;  
  14.   2  /  
  15.    
  16. Type created  
  17.    
  18. Executed in 0.031 seconds  
  19.    
  20. --1 創建普通函數 返回數組類型,用數組的實例存放結果集(t_array),結果集全部處理完成后一起返回  
  21. SQL> create or replace function f_test_array(n in number default null) return t_test_tb as  
  22.   2    t_array t_test_tb := t_test_tb();  
  23.   3  begin  
  24.   4    for i in 1..nvl(n,100) loop  
  25.   5        t_array.extend();  
  26.   6        t_array(t_array.count) := t_test(i,sysdate,'mi'||i);  
  27.   7    end loop;  
  28.   8    return t_array;  
  29.   9  end;  
  30.  10  /  
  31.    
  32. Function created  
  33.    
  34. Executed in 0.046 seconds  
  35.  --直接select是不能顯示的  
  36. SQL> select f_test_array(10) from dual;  
  37.    
  38. F_TEST_ARRAY(10)  
  39. ----------------  
  40. <Object>  
  41.    
  42. Executed in 0.062 seconds  
  43.  --對於返回類型是數組的那么用table()函數或者the  
  44. SQL> select * from table(f_test_array(10));  
  45.    
  46.         ID TIME        DATA  
  47. ---------- ----------- ------------------------------------------------------------  
  48.          1 2010-8-10 1 mi1  
  49.          2 2010-8-10 1 mi2  
  50.          3 2010-8-10 1 mi3  
  51.          4 2010-8-10 1 mi4  
  52.          5 2010-8-10 1 mi5  
  53.          6 2010-8-10 1 mi6  
  54.          7 2010-8-10 1 mi7  
  55.          8 2010-8-10 1 mi8  
  56.          9 2010-8-10 1 mi9  
  57.         10 2010-8-10 1 mi10  
  58.    
  59. 10 rows selected  
  60.    
  61. Executed in 0.187 seconds  
  62.    
  63. SQL> select * from the(select f_test_array(10) from dual);  
  64.    
  65.         ID TIME        DATA  
  66. ---------- ----------- ------------------------------------------------------------  
  67.          1 2010-8-10 1 mi1  
  68.          2 2010-8-10 1 mi2  
  69.          3 2010-8-10 1 mi3  
  70.          4 2010-8-10 1 mi4  
  71.          5 2010-8-10 1 mi5  
  72.          6 2010-8-10 1 mi6  
  73.          7 2010-8-10 1 mi7  
  74.          8 2010-8-10 1 mi8  
  75.          9 2010-8-10 1 mi9  
  76.         10 2010-8-10 1 mi10  
  77.    
  78. 10 rows selected  
  79.    
  80. Executed in 0.172 seconds  
  81.  --2 用返回類型為數組的管道函數,這里沒用用到存放中間結果的變量,每處理完一條記錄那么立刻返回結果  
  82. SQL> create or replace function f_test_pipe(n in number default null) return t_test_tb pipelined  
  83.   2  as  
  84.   3  begin  
  85.   4         for i in 1..nvl(n,100) loop  
  86.   5             pipe row(t_test(i,sysdate,'mi'||i));  
  87.   6         end loop;  
  88.   7         return;  
  89.   8  end;  
  90.   9  /  
  91.    
  92. Function created  
  93.    
  94. Executed in 0.031 seconds  
  95.    
  96. SQL> select f_test_pipe(10) from dual;  
  97.    
  98. F_TEST_PIPE(10)  
  99. ---------------  
  100. <Object>  
  101.    
  102. Executed in 0.062 seconds  
  103.    
  104. SQL> select * from table(f_test_pipe(10));  
  105.    
  106.         ID TIME        DATA  
  107. ---------- ----------- ------------------------------------------------------------  
  108.          1 2010-8-10 1 mi1  
  109.          2 2010-8-10 1 mi2  
  110.          3 2010-8-10 1 mi3  
  111.          4 2010-8-10 1 mi4  
  112.          5 2010-8-10 1 mi5  
  113.          6 2010-8-10 1 mi6  
  114.          7 2010-8-10 1 mi7  
  115.          8 2010-8-10 1 mi8  
  116.          9 2010-8-10 1 mi9  
  117.         10 2010-8-10 1 mi10  
  118.    
  119. 10 rows selected  
  120.    
  121. Executed in 0.156 seconds  
  122.    
  123. SQL> select * from the(select f_test_pipe(10) from dual);  
  124.    
  125.         ID TIME        DATA  
  126. ---------- ----------- ------------------------------------------------------------  
  127.          1 2010-8-10 1 mi1  
  128.          2 2010-8-10 1 mi2  
  129.          3 2010-8-10 1 mi3  
  130.          4 2010-8-10 1 mi4  
  131.          5 2010-8-10 1 mi5  
  132.          6 2010-8-10 1 mi6  
  133.          7 2010-8-10 1 mi7  
  134.          8 2010-8-10 1 mi8  
  135.          9 2010-8-10 1 mi9  
  136.         10 2010-8-10 1 mi10  
  137.    
  138. 10 rows selected  
  139.    
  140. Executed in 0.172 seconds  
  141.    
  142. SQL> drop table test;  
  143.    
  144. Table dropped  
  145.    
  146. Executed in 0.047 seconds  
  147.  --3 table調用包中返回為數組類型的函數 dbms_xplan.display 是返回類型為數組的管道函數  
  148. SQL> create table test(id number, name varchar2(30));  
  149.    
  150. Table created  
  151.    
  152. Executed in 0.047 seconds  
  153.    
  154. SQL> insert into test values(1,'d');  
  155.    
  156. 1 row inserted  
  157.    
  158. Executed in 0 seconds  
  159.    
  160. SQL> commit;  
  161.    
  162. Commit complete  
  163.    
  164. Executed in 0.016 seconds  
  165.    
  166. SQL> explain plan for select * from test;  
  167.    
  168. Explained  
  169.    
  170. Executed in 0 seconds  
  171.    
  172. SQL> select * from table(dbms_xplan.display);  
  173.    
  174. PLAN_TABLE_OUTPUT  
  175. --------------------------------------------------------------------------------  
  176. Plan hash value: 1357081020  
  177. --------------------------------------------------------------------------  
  178. | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
  179. --------------------------------------------------------------------------  
  180. |   0 | SELECT STATEMENT  |      |     1 |    30 |     3   (0)| 00:00:01 |  
  181. |   1 |  TABLE ACCESS FULL| TEST |     1 |    30 |     3   (0)| 00:00:01 |  
  182. --------------------------------------------------------------------------  
  183. Note  
  184. -----  
  185.    - dynamic sampling used for this statement  
  186.    
  187. 12 rows selected  
  188.    
  189. Executed in 0.187 seconds  
  190.    
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM