簡述
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. /
詳細分析
接下來,我們對這段代碼進行詳細分析。聲明和初始化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 ();
從指定的條目處取值
把條目的數目作為下標。下標可以是返回整數值(該值小於或等於數組條目數)的任意表達式,如:1. K := V(3); 2. I := 2; 3. L := V(I+1);
得到數組的容量
對VARRAY變數使用COUNT()方法。注意,你不需要指定圓括弧,因為這個方法沒有輸入參數:1. N_ENTRIES := V.COUNT();
這告訴你這個數組中正在使用的條目數。當VARRAY類型被聲明的時候,其最大的容量也就被定義了。你可以用LIMIT()方法得到該容量:
1. ARRAY_CAPACITY := V.LIMIT();
遍歷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。
對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);
對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空間信息管理》