plsql陣列學習

dawn009發表於2014-03-04
PLSQL中提供了三種資料的形式,功能還是比較強大的。但是總的來說,PLSQL中的陣列知識掌握最簡單的那種,其他大致瞭解就可以了。因為從實際應用的角度來說,在PLSQL中用到陣列的機率不是很大。這主要是由於PLSQL跟資料庫的緊密結合特性所決定的,資料庫的表可以很輕易得實現基本的陣列功能。當然這是我個人的一點理解,不一定正確。下面是詳細介紹
 
 
1、PLSQL中的陣列共分三類:
 
I  - 巢狀表(Nested tables)

TYPE nested_type IS TABLE OF VARCHAR2 ( 30 ) [not null];

-- 值為 varchar2 的陣列,下標為預設 int 

特徵:可刪除資訊,下標不變
 
II - 變長陣列(Variable-Sized Arrays)

TYPE Calendar IS VARRAY ( 366 OF NUMBER ;

--366  number 陣列,下標 1-366( 不是 0-365)

特徵:一般在可預知陣列個數的情況下使用,類似其他語言的Array
 
III- 索引表(Associative Array) 

TYPE population_type IS TABLE OF NUMBER

INDEX BY VARCHAR2 ( 64 );

-- 下標是 varchar2 ,值是 number 的陣列

特徵:可使用不連續數字、負數、字元作為下標,長度大小可變
      在建立陣列時便分配記憶體,無需之後申請
      index by 只能跟BINARY_INTEGERPLS_INTEGERVARCHAR2三種型別
 
 
2、陣列中的賦值錯誤問題:

 

DECLARE

  TYPE wordlist IS TABLE OF VARCHAR2 ( 5 );

  words wordlist;

BEGIN

  words( 1 )      := 10 ; --COLLECTION_IS_NULL, 未賦空間

  words         := wordlist( 10 , 20 , 30 ); -- 進行賦值

  words( 1 )      := 'yes' ; -- 正確

  words( 2 )      := words( 1 ) || 'no' ; -- 正確

  words( 3 )      := 'longer than 5 characters' ; --VALUE_ERROR ,字元過長

  words( 'B' )    := 'dunno' ; --VALUE_ERROR ,下標錯誤

  words( 4 )      := 'maybe' ; --SUBSCRIPT_BEYOND_COUNT ,下標超限

END ;

 
在宣告 words wordlist; 之後陣列未初始化,完全沒有用處
必須進行初始化,如:
words := wordlist( 10 , 20 , 30 );--定值初始化;
words := wordlist();--空值初始化,任何陣列必須先初始化;
words.extend(n);--末尾增加N位空間,不加N則為預設增加1位;
然後可以賦值
 
 
3、陣列相關集合函式:
 
1、EXISTS(判斷第i位是否存在)

IF courses.EXISTS(i) THEN

  courses(i)    := new_course;

END IF ;

 

2、COUNT(陣列中的元素個數)

FOR IN 1 .. courses.COUNT LOOP ...

注意:COUNT會忽略已經被刪除的元素

 

3、LIMIT(集合的最大容量)

IF (projects.COUNT + 15 ) < projects.LIMIT THEN ...

注意:LIMIT一般只對變長陣列有效(其他兩類均返回NULL)
 
4、FIRST和LAST(第一個和最後一個元素的下標)

FOR IN courses.FIRST .. courses.LAST LOOP ...

注意:返回值是下標,而不是值!在遍歷元素時,FIRST和LAST都會忽略被刪除的元素
 
5、PRIOR和NEXT(返回索引為n的前驅/後驅下標)

n := courses.PRIOR(courses.FIRST);  --assigns NULL to n

注意:返回值是下標,而不是值!在遍歷元素時,FIRST和LAST都會忽略被刪除的元素
 
6、EXTEND(擴大集合容量)

courses.EXTEND( m , n ); --將第n個元素的值複製m份加到集合末端

注意:m預設為1,n預設為null,m包含被刪除元素
 
7、TRIM(縮減集合容量)

courses.TRIM( 3 ); --  extend 相反

 
8、DELETE(刪除集合元素)

courses.DELETE      -- 刪除全部

courses.DELETE( 2 )   -- 刪除第 2 個元素

courses.DELETE( 2 , 5 -- 刪除第 2 到第 5 個元素

注意:使用delete的時候必須要結合3中陣列的不同特徵!
 
 
4、Exception的型別及原因:
 

COLLECTION_IS_NULL         --- 呼叫一個空集合的方法 , 集合未被初始化

NO_DATA_FOUND                --- 下標索引指向一個被刪除的元素,或是關聯陣列中不存在的元素

SUBSCRIPT_BEYOND_COUNT    --- 下標索引值超過集合中的元素個數

SUBSCRIPT_OUTSIDE_LIMIT --- 下標索引超過允許範圍之外

VALUE_ERROR                  --- 下標索引值為空,或是不是指定的下標型別

 
 
5、關於陣列的特有批次繫結ForAll
 
1、語法結構:

 

FORALL IN pnums.FIRST .. pnums.LAST

INSERT INTO partno VALUES (pnums(i));   ---注意:不用再Loop

 
 
2、可使用%BULK_ROWCOUNT屬性來計算FORALL語句所影響到的行數

 

IF SQL % BULK_ROWCOUNT ( 3 ) = 0 THEN ...


表示如果第3次操作沒有對資料影響的行數為0話……

注意%BULK_ROWCOUNT的值是可以大於1的,比如批次插入等

 
3、使用%BULK_EXCEPTIONS屬性來控制FORALL異常

 

DECLARE

  TYPE numlist IS TABLE OF NUMBER ;

 

  num_tab      numlist  := numlist( 10 0 11 12 30 0 20 199 2 0 9 1 );

  ERRORS        NUMBER ;

  dml_errors   EXCEPTION ;

  PRAGMA EXCEPTION_INIT (dml_errors, - 24381 );

BEGIN

  FORALL IN num_tab.FIRST .. num_tab.LAST SAVE EXCEPTIONS

    DELETE FROM emp

          WHERE sal > 500000 / num_tab(i);

EXCEPTION

  WHEN dml_errors THEN

    ERRORS     := SQL %BULK_EXCEPTIONS.COUNT;

    DBMS_OUTPUT.put_line( 'Number of errors is ' || ERRORS );

 

    FOR IN 1 .. ERRORS LOOP

      DBMS_OUTPUT.put_line(   'Error '

                           || i

                           || ' occurred during '

                           || 'iteration '

                           || SQL % BULK_EXCEPTIONS (i).ERROR_INDEX);

      DBMS_OUTPUT.put_line(   'Oracle error is '

                           || SQLERRM (- SQL % BULK_EXCEPTIONS (i).ERROR_CODE));

    END LOOP ;

END ;

 
 
 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29119536/viewspace-1100992/,如需轉載,請註明出處,否則將追究法律責任。

相關文章