标题：oracle varray
简述
VARRAY(varying array的简写)和其他任何程序语言中的数组都相似：存储确定数目的元素，但是它们具有可伸缩性。它们有一个最大的容量，当超过这个容量后将不再可扩展。它们的下标是从1开始的有序数字。也有许多方法用来操作数组中的各项。对方法的调用可通过在VARRAY变量名后添加相应的方法来实现。
VARRAY(与另一个集合格式NESTED TABLES相同)不是一个全新的类型，在Oracle数据库8.0版本中就可用了。它是Oracle对象/关系方面的基础部分。它使得定义多值属性成为一种可能：由此克服了关系模型的基本特征(也可以说是约束)，一个属性(如一个列)的每行只可以存储一个值。
VARRAY的一个强大功能就是它的元素可以是对象类型本身。而这些对象本身可以包含其他的VARRAY。这就使得构造复杂的结构，如集合或矩阵，成为一种可能，从而表示复杂的对象。然而，SDO_GEOMETRY类型没有使用如此复杂的结构，它只包含了两个数字数组。
VARRAY的另一个特性是有序性。这对几何基本元素尤其有用，因为点被定义的顺序是很重要的-- 以A、B、C、D顺序定义的形状与以A、C、B、D顺序定义的形状是明显不同的。
程序清单7-4中的代码展示了不同的数组操作。
程序清单7-4 对VARRAY的操作
1. SET SERVEROUTPUT ON 
2. DECLARE 
3. 
4. -- Declare a type for the VARRAY 
5. TYPE MY_ARRAY_TYPE IS VARRAY(10) OF NUMBER; 
6. 
7. -- Declare a VARRAY variable 
8. V MY_ARRAY_TYPE; 
9. 
10. -- Other variables 
11. I NUMBER; 
12. K NUMBER; 
13. L NUMBER; 
14. ARRAY_CAPACITY NUMBER; 
15. N_ENTRIES NUMBER; 
16. 
17. BEGIN
18. -- Initialize the array 
19. V := MY_ARRAY_TYPE (1,2,3,4); 
20. 
21. -- Get the value of a specific entry 
22. DBMS_OUTPUT.PUT_LINE('* Values for specific array entries'); 
23. K := V(3); 
24. DBMS_OUTPUT.PUT_LINE('V(3)='|| V(3)); 
25. I := 2; 
26. L := V(I+1); 
27. DBMS_OUTPUT.PUT_LINE('I=' || I); 
28. DBMS_OUTPUT.PUT_LINE('V(I+1)=' || V(I+1)); 
29. 
30. -- Find the capacity of a VARRAY: 
31. DBMS_OUTPUT.PUT_LINE('* Array capacity'); 
32. ARRAY_CAPACITY := V.LIMIT(); 
33. DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT()); 
34. N_ENTRIES := V.COUNT(); 
35. DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT()); 
36. 
37. -- Range over all values in a VARRAY 
38. DBMS_OUTPUT.PUT_LINE('* Array Content'); 
39. FOR I IN 1..V.COUNT() LOOP 
40. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 
41. END LOOP; 
42. 
43. FOR I IN V.FIRST()..V.LAST() LOOP 
44. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 
45. END LOOP; 
46. 
47. I := V.COUNT(); 
48. WHILE I IS NOT NULL LOOP 
49. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 
50. I := V.PRIOR(I); 
51. END LOOP; 
52. 
53. -- Extend the VARRAY 
54. DBMS_OUTPUT.PUT_LINE('* Extend the array'); 
55. I := V.LAST(); 
56. V.EXTEND(2); 
57. V(I+1) := 5; 
58. V(I+2) := 6; 
59. 
60. DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT()); 
61. DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT()); 
62. FOR I IN 1..V.COUNT() LOOP 
63. DBMS_OUTPUT.PUT_LINE('V('||I||')='|| V(I)); 
64. END LOOP; 
65. 
66. -- Shrink the VARRAY 
67. DBMS_OUTPUT.PUT_LINE('* Trim the array'); 
68. V.TRIM(); 
69. 
70. DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT()); 
71. DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT()); 
72. FOR I IN 1..V.COUNT() LOOP 
73. DBMS_OUTPUT.PUT_LINE('V('||I||')='|| V(I)); 
74. END LOOP; 
75. 
76. -- Delete all entries from the VARRAY 
77. DBMS_OUTPUT.PUT_LINE('* Empty the array'); 
78. V.DELETE(); 
79. 
80. DBMS_OUTPUT.PUT_LINE('Array Capacity: V.LIMIT()='||V.LIMIT()); 
81. DBMS_OUTPUT.PUT_LINE('Current Array Size: V.COUNT()='||V.COUNT()); 
82. FOR I IN 1..V.COUNT() LOOP 
83. DBMS_OUTPUT.PUT_LINE('V('||I||')='|| V(I)); 
84. END LOOP; 
85. END; 
86. / 
详细分析
接下来，我们对这段代码进行详细分析。
1. 声明和初始化VARRAY变量你不可以直接声明一个VARRAY变量。必须先声明一个包含这个数组最大容量的类型：
1. TYPE MY_ARRAY_TYPE IS VARRAY(10) OF NUMBER; 
然后，你就可以用这个类型声明VARRAY变量：
1. V MY_ARRAY_TYPE; 
在你对这个数组进行操作以前，必须先初始化该数组。你既可以在声明它的时候对其初始化，也可以在声明后对其赋值。下面展示了在声明的同时对其进行初始化：
1. V MY_ARRAY_TYPE := MY_ARRAY_TYPE (); 
2. 从指定的条目处取值把条目的数目作为下标。下标可以是返回整数值(该值小于或等于数组条目数)的任意表达式，如：
1. K := V(3); 2. I := 2; 3. L := V(I+1); 
3. 得到数组的容量对VARRAY变量使用COUNT()方法。注意，你不需要指定圆括号，因为这个方法没有输入参数：
1. N_ENTRIES := V.COUNT(); 
这告诉你这个数组中正在使用的条目数。当VARRAY类型被声明的时候，其最大的容量也就被定义了。你可以用LIMIT()方法得到该容量：
1. ARRAY_CAPACITY := V.LIMIT(); 
4. 遍历VARRAY中的值你可以使用多种技术。最简单的是使用FOR循环：
1. FOR I IN 1..V.COUNT() LOOP 2. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 3. END LOOP; 
你也可以使用FIRST()和LAST()方法。FIRST()返回数组的第一个条目的下标(总是1)，LAST()返回数组的最后一个条目的下标(与COUNT方法相同)。
1. FOR I IN V.FIRST()..V.LAST() LOOP 2. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 3. END LOOP; 
你也可以使用PRIOR(n)和NEXT(n)方法，这两个方法分别返回给定条目的前一个和后一个条目的下标。例如，下面的代码用来向后遍历整个数组：
1. I := V.COUNT(); 2. WHILE I IS NOT NULL LOOP 3. DBMS_OUTPUT.PUT_LINE('V('||I||')=' || V(I)); 4. I := V.PRIOR(I); 5. END LOOP; 
PRIOR(n)和n-1是一样的，NEXT(n)和n+1是一样的，但是PRIOR(1)和NEXT(V.COUNT())则返回NULL。
5. 对VARRAY的扩展使用EXTEND(k)方法。这个方法可以在VARRAY的最后追加k个新的条目。如果k没有被指定，只增加一个条目。新增的条目没有值(默认为NULL)，但是你可以对它们进行初始化。COUNT()和LAST()方法现在可以反映VARRAY新的容量。以下代码向数组中添加两个条目并对其进行初始化：
1. I := V.LAST(); 2. V.EXTEND(2); 3. V(I+1) := 5; 4. V(I+2) := 6; 
注意，你对VARRAY的扩展不可以超过其最大容量(通过LIMIT()方法得到)，且在对VARRAY扩展前必须要对其进行初始化。以下代码是无效的：
1. VT MY_ARRAY_TYPE; 2. VT.EXTEND(5); 
下面的代码是有效的：
1. VT MY_ARRAY_TYPE; 2. VT := MY_ARRAY_TYPE(); 3. VT.EXTEND(5); 
6. 对VARRAY的缩减使用TRIM(k)方法。这个方法在VARRAY的尾部删除最后k个条目。当k没有被指定时，删除最后一个条目。已被删除的条目的值将丢失。COUNT()和LAST()方法反映了新的容量。下面从VARRAY中删除最后一个条目：
1. V.TRIM; 
你也可以用以下方式删除数组中的所有条目：
1. V.TRIM(V.COUNT()); 
或者用具有效果相同的DELETE()方法。该方法删除数组中的所有条目，并把其容量设置为0(也就是说，V.COUNT()现在的返回值为0)。
1. V.DELETE() 
现在你知道怎样对VARRAY进行操作了，让我们把它应用到SDO_GEOMETRY类型上。我们首先将用该技术从SDO_GEOMETRY对象中提取信息，然后将给出一个例子，来展示怎样对SDO_GEOMETRY对象进行更新。
接下来，我们将回到最初的关于怎样对SDO_GEOMETRY数据进行读写，怎样创建新的几何体，怎样从存在的对象中提取信息和怎样对存在的几何体进行修改的讨论中去。我们将对这些主题进行分节介绍。
《Oracle Spatial空间信息管理》 [1]