全部產品
Search
文件中心

PolarDB:關聯陣列

更新時間:Jul 06, 2024

關聯陣列是一種將唯一鍵與值相關聯的集合。鍵不必是數字,也可以是字元資料。

關聯陣列具有以下特徵:

  • 必須定義關聯陣列類型,然後才能聲明該數群組類型的陣列變數。使用陣列變數進行資料操作。
  • 聲明陣列變數時,會建立關聯陣列,但它是空的 - 只需開始為索引值賦值即可。
  • 如果指定了INDEXBY BINARY_INTEGER或PLS_INTEGER,則鍵可以是任何負整數、正整數或零。
  • 如果指定了INDEXBY VARCHAR2,則鍵可以是字元資料。
  • 數組中的元素數量沒有預定義的限制 - 它會隨著添加的元素而動態增長。
  • 數組可能是稀疏的 - 在索引值的賦值中可能存在間隙。
  • 嘗試引用尚未賦值的數組元素將導致異常。

TYPE IS TABLE OF ... INDEX BY語句用於定義關聯陣列類型。

TYPE assoctype IS TABLE OF { datatype | rectype | objtype }
  INDEX BY { BINARY_INTEGER | PLS_INTEGER | VARCHAR2(n) };

assoctype是分配給數群組類型的標識符。datatype是純量資料型別,例如VARCHAR2或NUMBER。rectype是先前定義的記錄類型。objtype 是先前定義的物件類型。n是字元鍵的最大長度。

為了使用該數組,必須聲明一個該數群組類型的變數。以下是聲明陣列變數的文法。

array assoctype

array是分配給關聯陣列的標識符。assoctype是先前定義的數群組類型的標識符。

使用以下文法引用數組的元素。

array(n)[.field ]

array是先前聲明的數組的標識符。n是索引值,其類型與INDEX BY子句中給出的資料類型相容。如果從屬記錄類型或物件類型定義array的數群組類型,則 [.field ] 必須引用定義數群組類型時所依據的物件類型中的記錄類型或屬性內的單個欄位。或者,可以通過省略 [.field ] 來引用整個記錄。

以下樣本從emp表中讀取前十名員工的姓名,將它們儲存在一個數組中,然後顯示數組中的結果。

DECLARE
    TYPE emp_arr_typ IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;
    emp_arr         emp_arr_typ;
    CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 10;
    i               INTEGER := 0;
BEGIN
    FOR r_emp IN emp_cur LOOP
        i := i + 1;
        emp_arr(i) := r_emp.ename;
    END LOOP;
    FOR j IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE(emp_arr(j));
    END LOOP;
END;

上面的樣本產生以下輸出:

SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER

現在修改上一個樣本以使用數組定義中的記錄類型。

DECLARE
    TYPE emp_rec_typ IS RECORD (
        empno       NUMBER(4),
        ename       VARCHAR2(10)
    );
    TYPE emp_arr_typ IS TABLE OF emp_rec_typ INDEX BY BINARY_INTEGER;
    emp_arr         emp_arr_typ;
    CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
    i               INTEGER := 0;
BEGIN
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    FOR r_emp IN emp_cur LOOP
        i := i + 1;
        emp_arr(i).empno := r_emp.empno;
        emp_arr(i).ename := r_emp.ename;
    END LOOP;
    FOR j IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || '     ' ||
            emp_arr(j).ename);
    END LOOP;
END;

下面是此匿名塊的輸出。

EMPNO    ENAME
-----    -------
7369     SMITH
7499     ALLEN
7521     WARD
7566     JONES
7654     MARTIN
7698     BLAKE
7782     CLARK
7788     SCOTT
7839     KING
7844     TURNER

emp%ROWTYPE屬性可用於定義emp_arr_typ,而不是使用emp_rec_typ記錄類型,如下所示。

DECLARE
    TYPE emp_arr_typ IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
    emp_arr         emp_arr_typ;
    CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
    i               INTEGER := 0;
BEGIN
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    FOR r_emp IN emp_cur LOOP
        i := i + 1;
        emp_arr(i).empno := r_emp.empno;
        emp_arr(i).ename := r_emp.ename;
    END LOOP;
    FOR j IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || '     ' ||
            emp_arr(j).ename);
    END LOOP;
END;

結果與前面的例子相同。

不是單獨分配記錄的每個欄位,而是可以從r_emp到emp_arr進行記錄層級分配。

DECLARE
    TYPE emp_rec_typ IS RECORD (
        empno       NUMBER(4),
        ename       VARCHAR2(10)
    );
    TYPE emp_arr_typ IS TABLE OF emp_rec_typ INDEX BY BINARY_INTEGER;
    emp_arr         emp_arr_typ;
    CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
    i               INTEGER := 0;
BEGIN
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------');
    FOR r_emp IN emp_cur LOOP
        i := i + 1;
        emp_arr(i) := r_emp;
    END LOOP;
    FOR j IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || '     ' ||
            emp_arr(j).ename);
    END LOOP;
END;

關聯陣列的鍵可以是字元資料,如以下樣本所示。

DECLARE
    TYPE job_arr_typ IS TABLE OF NUMBER INDEX BY VARCHAR2(9);
    job_arr         job_arr_typ;
BEGIN
    job_arr('ANALYST')   := 100;
    job_arr('CLERK')     := 200;
    job_arr('MANAGER')   := 300;
    job_arr('SALESMAN')  := 400;
    job_arr('PRESIDENT') := 500;
    DBMS_OUTPUT.PUT_LINE('ANALYST  : ' || job_arr('ANALYST'));
    DBMS_OUTPUT.PUT_LINE('CLERK    : ' || job_arr('CLERK'));
    DBMS_OUTPUT.PUT_LINE('MANAGER  : ' || job_arr('MANAGER'));
    DBMS_OUTPUT.PUT_LINE('SALESMAN : ' || job_arr('SALESMAN'));
    DBMS_OUTPUT.PUT_LINE('PRESIDENT: ' || job_arr('PRESIDENT'));
END;

ANALYST  : 100
CLERK    : 200
MANAGER  : 300
SALESMAN : 400
PRESIDENT: 500

二維關聯陣列

二維關聯陣列是嵌套的關聯陣列,二維關聯陣列的值是一維關聯陣列,可以同時使用兩個鍵關聯到最內層關聯陣列的元素。二維關聯陣列的基本特徵和關聯陣列相同。

  • 二維關聯陣列支援的情境
    在只有一維關聯陣列的情況下,如果需要實作類別似二維關聯陣列的功能,需要使用一個中轉表間接實現,樣本如下:
    DECLARE
        type TB1 is table of varchar(10) index by varchar(10);
        type TB2 is table of TB1 index by varchar(10);
        v_table1 TB1;
        v_table2 TB2;
    BEGIN
        v_table1('a') := 1;
        v_table1('b') := 2;
        v_table1('c') := 3;
        v_table2('a') := v_table1;
    END;
    在支援了二維關聯陣列後,可以不用定義中轉數組v_table1,直接使用二維下標,對v_table2完成賦值操作:
    DECLARE
        type TB1 is table of varchar(10) index by varchar(10);
        type TB2 is table of TB1 index by varchar(10);
        v_table2 TB2;
    BEGIN
        v_table2('a')('a') := 1;
        v_table2('a')('b') := 2;
        v_table2('a')('c') := 3;
    END;
  • 樣本
    使用二維關聯陣列樣本如下所示:
    -- Examples of dim-2 associative array 
    DECLARE
        type type_row is table of varchar(10) index by varchar(10);
        type type_table is table of type_row index by varchar(10);
        v_table type_table;
        i varchar2(64);
        i_2 varchar2(64);
    BEGIN
        v_table('a')('b') := 10;
        v_table('a')('c') := 11;
        v_table('z')('b') := 12;
        v_table('z')('c') := 13;
        i := v_table.FIRST;
        WHILE i IS NOT NULL LOOP
            i_2 := v_table(i).FIRST;
            WHILE i_2 IS NOT NULL LOOP
                dbms_output.put_line(i || ' ' || i_2 || '-' || TO_CHAR(v_table(i)(i_2)));
                i_2 := v_table(i).NEXT(i_2);
            END LOOP;
            i := v_table.NEXT(i);
        END LOOP;
    END;
    以下是此匿名塊的輸出:
    a b-10
    a c-11
    z b-12
    z c-13
  • 集合方法
    目前二維關聯陣列支援的集合方法有:COUNT,FIRST,LAST,NEXT,PRIOR,EXISTS。
    -- 對於無參數的集合方法,比如COUNT,採用如下形式的方法進行調用:
    array_dim2(n)
    -- 對於含有一個參數的集合方法,比如NEXT,採用如下形式的方法進行調用:
    array_dim2(n).op(n)
    說明
    • array_dim2:為先前聲明的二維關聯陣列的標識符。
    • n:為索引值,其類型與INDEX BY子句中給出的資料類型相容。
    • op:為集合方法。
    以下為一個二維關聯陣列使用集合方法的樣本:
    DECLARE
        type TB1 is table of varchar(10) index by varchar(10);
        type TB2 is table of TB1 index by varchar(10);
        type TB3 is table of TB2 index by varchar(10);
        v_table TB2;
        v_table3 TB3;
    BEGIN
        v_table('a')('b') := 10;
        v_table('b')('c') := 11;
        v_table('c')('b') := 12;
        v_table('d')('c') := 13;
        v_table3('a') := v_table;
        
        dbms_output.put_line(v_table3('a').COUNT); 
        dbms_output.put_line(v_table3('a').FIRST);
        dbms_output.put_line(v_table3('a').LAST); 
        dbms_output.put_line(v_table3('a').NEXT(v_table3('a').FIRST));
        dbms_output.put_line(v_table3('a').prior(v_table3('a').LAST));
        dbms_output.put_line(v_table3('a').exists(v_table3('a').FIRST));
    END;
    以下是此匿名塊的輸出:
    4
    a
    d
    b
    c
    t
  • 暫不支援的情境

    目前只支援二維的關聯陣列,巢狀表格和varray目前還不支援二維下標操作。

    目前二維關聯陣列還不支援記錄類型(record類型):
    DECLARE
        TYPE emp_typ IS RECORD (
            ename       varchar(10),
            first         varchar(10)
        );
        type TB is table of emp_typ index by varchar(10);
        type TB2 is table of TB index by varchar(10);
        mytable     TB2;
        myrecord    emp_typ;
    BEGIN
        mytable('a')('b') := myrecord;
    END;
    以下是此匿名塊的輸出:
    ERROR:  At present, only associative array without package and IS TABLE OF type is not record type support multidimensional subscripts search and assignment
    CONTEXT:  compilation of SPL function "inline_code_block" near line 11
    巢狀表格和varray不能包含一個二維關聯陣列,樣本如下:
    DECLARE
        type TB1 is table of number index by number;
        type TB2 is table of TB1 index by number;
        type TB3 is table of TB2;
        v_table2 TB2;
        v_table3 TB3;
    BEGIN
        v_table2(1)(1) := 1;
        v_table2(1)(2) := 2;
        v_table2(2)(3) := 3;
        v_table2(2)(4) := 4;
    
        v_table3 := TB3(v_table2);
    END;
    以下是此匿名塊的輸出:
    ERROR:  Nested table and Varray can't be assgined with a multidimensional associative array