PL/SQL 集合的方法

PL/SQL 集合的方法

转自:http://blog.csdn.net/leshami/article/details/7529361

PL/SQL中提供了常用的三种集合联合数组、嵌套表、变长数组,而对于这几个集合类型中元素的操作,PL/SQL提供了相应的函数或过程来操作数组中的元素或下标。这些函数或过程称为集合方法。一个集合方法就是一个内置于集合中并且能够操作集合的函数或过程,可以通过点标志来调用。本文主要描述如何操作这些方法。

一、集合类型提供的方法与调用方式

1、集合的方法与调用方式
      EXISTS
              函数EXISTS(n)在第n个元素存在的情况下会返回TRUE,否则返回FALSE。     
              通常使用EXISTS和DELETE来维护嵌套表。其中EXISTS还可以防止引用不存在的元素,避免发生异常。
              当下标越界时,EXISTS会返回FALSE,而不是抛出SUBSCRIPT_OUTSIDE_LIMIT异常。

      COUNT
              COUNT能够返回集合所包含的元素个数,对于大小不确定的情形则COUNT非常有用。
              可以在任何可以使用整数表达式的地方使用COUNT函数,如作为for循环的上限。
              计算元素个数时,被删除的元素不会被count所统计。
              对于变长数组来说,COUNT值与LAST值恒等。
              对于嵌套表来说,正常情况下COUNT值会和LAST值相等。但是,当我们从嵌套表中间删除一个元素,COUNT值就会比LAST值小。
                     
      LIMIT
              用于检测集合的最大容量
              由于嵌套表和关联数组都没有上界限制,所以LIMIT总会返回NULL。
              对于变长数组,LIMIT会返回它所能容纳元素的个数最大值,该值是在变长数组声明时指定的,并可用TRIM和EXTEND方法调整。
                             
      FIRST,LAST
              FIRST和LAST会返回集合中第一个和最后一个元素在集合中的下标索引值。
              对于使用VARCHAR2类型作为键的关联数组来说,会分别返回最低和最高的键值;键值的高低顺序是基于字符串中字符的二进制值。
              但是,如果初始化参数NLS_COMP被设置成ANSI的话,键值的高低顺序就受初始化参数NLS_SORT所影响了。
              空集合的FIRST和LAST方法总是返回NULL。只有一个元素的集合,FIRST和LAST会返回相同的索引值。
              对于变长数组,FIRST恒等于1,LAST恒等于COUNT。
              对于嵌套表,FIRST通常返回1,如果删除第一个元素,则FIRST的值大于1,如果删除中间的一个元素,此时LAST就会比COUNT大。
              在遍历元素时,FIRST和LAST都会忽略被删除的元素。

      PRIOR,NEXT,
              PRIOR(n)会返回集合中索引为n的元素的前驱索引值;NEXT(n)会返回集合中索引为n的元素的后继索引值。
              如果n没有前驱或后继,PRIOR(n)或NEXT(n)就会返回NULL。
              对于使用VARCHAR2作为键的关联数组来说,它们会分别返回最低和最高的键值;键值的高低顺序是基于字符串中字符的二进制值。
              PRIOR和NEXT不会从集合的一端到达集合的另一端,即最末尾元素的的next不会指向集合中的first。
              在遍历元素时,PRIOR和NEXT都会忽略被删除的元素,即如果prior(3)之前的2被删除则指向1,如果1也被删除则返回null。

      EXTEND
              用于扩大嵌套表或变长数组的容量,该方法不能用于联合数组。
              EXTEND有三种形式
                      EXTEND 在集合末端添加一个空元素
                      EXTEND(n) 在集合末端添加n个空元素
                      EXTEND(n,i) 把第i个元素拷贝n份,并添加到集合的末端
              对嵌套表或变长数组添加了NOT NULL约束之后,不能使用EXTEND的前两种形式。
              EXTEND操作的是集合内部大小,其中也包括被删除的元素。所以,在计算元素个数的时候,EXTEND也会把被删除的元素考虑在内。
              对于使用DELETE方法操作的元素,PL/SQL会保留其占位符,后续可以重新利用。
                             
      TRIM
              从集合的末尾删除一个(TRIM)或指定数量TRIM(n)的元素,PL/SQL对TRIM掉的元素不再保留占位符。
              如果n值过大的话,TRIM(n)就会抛出SUBSCRIPT_BEYOND_COUNT异常。
              通常,不要同时使用TRIM和DELETE方法。可把嵌套表当作定长数组,只使用DELETE方法,或是当作栈,只对它使用TRIM和EXTEND方法。
             
      DELETE
              删除集合中的所有或指定范围的元素,通常有下列调用方式。
              DELETE 删除集合中所有元素 。
              DELETE(n) 从以数字作主键的关联数组或者嵌套表中删除第n个元素。
                      如果关联数组有一个字符串键,对应该键值的元素就会被删除。如果n为空,DELETE(n)不会做任何事情。
              DELETE(m,n) 从关联数组或嵌套表中,把索引范围m到n的所有元素删除。
                      如果m值大于n或是m和n中有一个为空,那么DELETE(m,n)就不做任何事。
                      PL/SQL会为使用DELETE方式删除的元素保留一个占位符,后续可以重新为被删除的元素赋值。
                      注,不能使用delete方式删除变长数组中的元素。
                                             

调用方式:
      collection_name.method_name[(parameters)]  

     
2、集合方法注意事项
      集合的方法不能在SQL语句中使用。
      EXTEND和TRIM方法不能用于关联数组。
      EXISTS,COUNT,LIMIT,FIRST,LAST,PRIOR和NEXT是函数;
      EXTEND,TRIM和DELETE是过程。
      EXISTS,PRIOR,NEXT,TRIM,EXTEND和DELETE对应的参数是集合的下标索引,通常是整数,但对于关联数组来说也可能是字符串。
      只有EXISTS能用于空集合,如果在空集合上调用其它方法,PL/SQL就会抛出异常COLLECTION_IS_NULL。

     
二、各个方法综合演示

-->示例1   

DECLARE  
    output                    VARCHAR2( 300 );  
    TYPE index_by_type IS TABLE OF VARCHAR2( 10 )  
                                                      INDEX BY BINARY_INTEGER;  
    index_by_table    index_by_type;  
    TYPE nested_type IS TABLE OF NUMBER;  
    nested_table        nested_type                                                    -->在声明块对嵌套表进行初始化并赋值   
                                            := nested_type( 10,20,30,40 ,50 ,60 ,70,80 ,90,100 );  
BEGIN  
    -- Populate index by table   
    FOR i IN 1 .. 10                                                                            -->在执行块对联合数组赋值   
    LOOP  
          index_by_table( i ) := 'Value_' || i;  
    END LOOP;  
 
    DBMS_OUTPUT.put_line( '--------------------------- Before deleted -----------------------------------------' );  
 
    FOR i IN index_by_table.FIRST .. index_by_table.LAST    -->使用了first,last作循环计数器上下标,输出当前联合数组的所有元素   
    LOOP  
          output := output || NVL( TO_CHAR( index_by_table( i ) ), 'NULL' ) || '  ';  
    END LOOP;  
 
    DBMS_OUTPUT.put_line( 'Element of Index_by_table are: ' || output );  
    output := '';  
 
    FOR i IN 1 .. nested_table.COUNT                                          -->使用了count作循环计数器上下标,输出当前嵌套表的所有元素   
    LOOP  
          output := output || NVL( TO_CHAR( nested_table( i ) ), 'NULL' ) || '  ';  
    END LOOP;  
 
    DBMS_OUTPUT.put_line( 'Element of nested_table are: ' || output );  
 
    IF index_by_table.EXISTS( 3 ) THEN            -->EXISTS函数判断联合数组中的第3个元素是否存在   
          DBMS_OUTPUT.put_line( 'index_by_table(3) exists and the value is ' || index_by_table( 3 ) );  
    END IF;  
 
    -- delete 10th element from a collection   
    nested_table.delete( 10 );  
    -- delete elements 1 through 3 from a collection   
    nested_table.delete( 1, 3 );  
    index_by_table.delete( 10 );  
   
    DBMS_OUTPUT.put_line( 'nested_table.COUNT = ' || nested_table.COUNT );  
    DBMS_OUTPUT.put_line( 'index_by_table.COUNT = ' || index_by_table.COUNT );  
   
    DBMS_OUTPUT.put_line( 'nested_table.FIRST = ' || nested_table.FIRST );  
    DBMS_OUTPUT.put_line( 'nested_table.LAST = ' || nested_table.LAST );  
    DBMS_OUTPUT.put_line( 'index_by_table.FIRST = ' || index_by_table.FIRST );  
    DBMS_OUTPUT.put_line( 'index_by_table.LAST = ' || index_by_table.LAST );  
   
    DBMS_OUTPUT.put_line( 'nested_table.PRIOR(2) = ' || nested_table.PRIOR( 2 ) );  
    DBMS_OUTPUT.put_line( 'nested_table.NEXT(2) = ' || nested_table.NEXT( 2 ) );  
    DBMS_OUTPUT.put_line( 'index_by_table.PRIOR(2) = ' || index_by_table.PRIOR( 2 ) );  
    DBMS_OUTPUT.put_line( 'index_by_table.NEXT(2) = ' || index_by_table.NEXT( 2 ) );  
   
    -- Trim last two elements   
    nested_table.TRIM( 2 );  
   
    -- Trim last element   
    nested_table.TRIM;  
   
    DBMS_OUTPUT.put_line( 'nested_table.LAST = ' || nested_table.LAST );  
    DBMS_OUTPUT.put_line( '--------------------------- After deleted -----------------------------------------' );  
 
  output:='';  
    FOR i IN index_by_table.FIRST .. index_by_table.LAST        -->输出删除元素后联合数组的所有剩余元素   
    LOOP  
          output := output || NVL( TO_CHAR( index_by_table( i ) ), 'NULL' ) || '  ';  
    END LOOP;  
 
    DBMS_OUTPUT.put_line( 'Element of Index_by_table are: ' || output );  
    output := '';  
 
  output:='';  
    FOR i IN  nested_table.FIRST .. nested_table.LAST            -->输出删除元素后嵌套表的所有剩余元素   
    LOOP  
          output := output || NVL( TO_CHAR( nested_table( i ) ), 'NULL' ) || '  ';  
    END LOOP;  
 
    DBMS_OUTPUT.put_line( 'Element of nested_table are: ' || output );  
END;  
 
--------------------------- Before deleted -----------------------------------------   
Element of Index_by_table are: Value_1  Value_2  Value_3  Value_4  Value_5  Value_6  Value_7  Value_8  Value_9  Value_10  
Element of nested_table are: 10  20  30  40  50  60  70  80  90  100  
index_by_table(3) exists and the value is Value_3  
nested_table.COUNT = 6          -->嵌套表使用了两次delete,分别是删除最后一个元素和删除第1到第3个元素,因此嵌套表的count输出为6   
index_by_table.COUNT = 9      -->联合数组中删除了最后的一个元素,因此联合数组的count输出为9   
nested_table.FIRST = 4          -->嵌套表删除了第1到第3个元素,因此其first变成4   
nested_table.LAST = 9            -->嵌套表删除了最后一个元素,因此last变成9   
index_by_table.FIRST = 1  
index_by_table.LAST = 9  
nested_table.PRIOR(2) =        -->嵌套表的PRIOR(2),第2个元素的前一个(下标为1),由于1-3都被删除,且1之前没有任何元素,故为NULL   
nested_table.NEXT(2) = 4      -->嵌套表2之后元素的下标,原本应该是3,由于3被删除,因此3被忽略,返回4   
index_by_table.PRIOR(2) = 1  
index_by_table.NEXT(2) = 3     
nested_table.LAST = 7          -->nested_table.TRIM(2)与nested_table.TRIM总共删除了3个元素及占位符,故LAST为7。   

--------------------------- After deleted -----------------------------------------   
Element of Index_by_table are: Value_1  Value_2  Value_3  Value_4  Value_5  Value_6  Value_7  Value_8  Value_9  
Element of nested_table are: 40  50  60  70  
 
PL/SQL procedure successfully completed.  
----------------------------------------------------------------------------------------------------------------------------                   



-->示例2   

DECLARE  
    TYPE varray_type IS VARRAY(10) OF NUMBER;  
    varray varray_type := varray_type(1, 2, 3, 4, 5, 6);  
    PROCEDURE print_numlist( the_list varray_type ) IS  
          output    VARCHAR2( 128 );  
    BEGIN  
          FOR i IN the_list.FIRST .. the_list.LAST  
          LOOP  
                output := output || NVL( TO_CHAR( the_list( i ) ), 'NULL' ) || ' ';  
          END LOOP;  
 
          DBMS_OUTPUT.put_line( output );  
    END;  
BEGIN  
    print_numlist( varray );  
    DBMS_OUTPUT.put_line( 'varray.COUNT = ' || varray.COUNT );  
    DBMS_OUTPUT.put_line( 'varray.LIMIT = ' || varray.LIMIT );  
    DBMS_OUTPUT.put_line( 'varray.FIRST = ' || varray.FIRST );  
    DBMS_OUTPUT.put_line( 'varray.LAST = ' || varray.LAST );  
    DBMS_OUTPUT.put_line( 'The maximum number you can use with ' || 'varray.EXTEND() is ' || ( varray.LIMIT - varray.COUNT ) );  
    varray.EXTEND( 2, 4 );              -->将第4个元素的值复制2份,追加到集合尾部   
    DBMS_OUTPUT.put_line( 'varray.LAST = ' || varray.LAST );  
    DBMS_OUTPUT.put_line( 'varray(' || varray.LAST || ') = ' || varray( varray.LAST ) );  
    print_numlist( varray );  
   
    -- Trim last two elements   
    varray.TRIM( 2 );  
    DBMS_OUTPUT.put_line( 'varray.LAST = ' || varray.LAST );  
END;  
 
1 2 3 4 5 6                            -->输出varray中的所有元素   
varray.COUNT = 6  
varray.LIMIT = 10                -->limit方法得到变长数组的最大容量   
varray.FIRST = 1  
varray.LAST = 6  
The maximum number you can use with varray.EXTEND() is 4    -->得到可以extend的容量,即还可以保存4个元素   
varray.LAST = 8                  --> extend之后last的下标值为8   
varray(8) = 4                      -->第8个元素的值则为4   
1 2 3 4 5 6 4 4                  -->输出varray中的所有元素   
varray.LAST = 6                  -->由于使用了varray.TRIM( 2 ),所以last又变成了6   
 
PL/SQL procedure successfully completed.  
 
-->Author : Robinson Cheng   
-->Blog    : http://blog.csdn.net/robinson_0612  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值