关联数组

区别于变长数组和嵌套表的形如数组的使用形式,关联数组(associative array)是一组键值对,使用形式更像是哈希表。

语法

关联数组支持在包和存储过程声明段(即DECLARE段)声明。关联数组类型的声明语法如下:

TYPE type_name IS TABLE OF value_type [ NULL | NOT NULL ] INDEX BY key_type ';'

其中key_type只支持字符类型(如VARCHAR2)与数字类型(如INTEGER)。

示例

基本示例

DECLARE
    TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10); -- 声明 associative array 局部类型
    PROCEDURE set_array(aarray IN OUT aarray_type) IS
        i INT;
    BEGIN
        FOR i IN 1..5 LOOP
            aarray(i) := i;  -- 赋值
        END LOOP;
    END;
    aarray aarray_type;  -- 创建变量
BEGIN
    set_array(aarray);
    RAISE NOTICE '%', aarray;  -- 取值
END;

返回结果如下:

NOTICE:  {1,2,3,4,5}
DO

关联数组声明索引类型

相比于嵌套表,关联数组的声明语法增加INDEX BY index_type部分,用于声明索引的类型。索引的排序方式由索引类型的排序顺序决定。目前支持正整数或字符串作为索引类型。关联数组会被默认初始化为空,因此您可以对特定索引位置直接进行赋值。如果在取值前没有对该索引位置进行赋值,会出现不存在该元素的错误。以下是一个尝试获取不存在的元素的示例:

DECLARE
  TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);
  aarray aarray_type;
BEGIN
  RAISE NOTICE '%', aarray('b');
END;

返回结果如下:

ERROR:  associatvie arrays element is not exist
CONTEXT:  PL/SQL function inline_code_block line 5 at RAISE

在包中声明并使用关联数组

在包中声明关联数组变量,通过存储过程OUT参数进行赋值:

CREATE OR REPLACE PACKAGE test_package IS
    TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);  -- 声明 associative array 全局类型
    PROCEDURE set_array(aarray IN OUT aarray_type);
END;

CREATE OR REPLACE PACKAGE BODY test_package IS
    PROCEDURE set_array(aarray IN OUT aarray_type) IS
        i INT;
    BEGIN
        FOR i IN 1..5 LOOP
            aarray(i) := i;  -- 赋值
        END LOOP;
    END;
END;

DECLARE
    aarray test_package.aarray_type;  -- 创建变量
BEGIN
    test_package.set_array(aarray);
    RAISE NOTICE '%', aarray;  -- 取值
END;

返回结果如下:

NOTICE:  {1,2,3,4,5}
DO

关联数组作为函数OUT参数与返回值

CREATE OR REPLACE PACKAGE test_package IS
    TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);  -- 声明 associative array 全局类型
    FUNCTION get_array(aarray IN OUT aarray_type) RETURN aarray_type;
END;

CREATE OR REPLACE PACKAGE BODY test_package IS
    FUNCTION get_array(aarray IN OUT aarray_type) RETURN aarray_type IS
        i INT;
    BEGIN
        FOR i IN 1..5 LOOP
            aarray(i) := i + 100;
        END LOOP;
        RETURN aarray;
    END;
END;

DECLARE
    aarray1 test_package.aarray_type;
    aarray2 test_package.aarray_type;
BEGIN
    aarray2 := test_package.get_array(aarray1);
    RAISE NOTICE 'aarray1 is %', aarray1;  -- 取值
    RAISE NOTICE 'aarray2 is %', aarray2;  -- 取值
    aarray1(1) := 1;
    aarray1(2) := 2;
    aarray1(3) := 3;
    aarray1(4) := 4;
    aarray1(5) := 5;
    RAISE NOTICE 'aarray1 is %', aarray1;  -- 取值
    RAISE NOTICE 'aarray2 is %', aarray2;  -- 取值
END;

返回结果如下:

NOTICE:  aarray1 is {101,102,103,104,105}
NOTICE:  aarray2 is {101,102,103,104,105}
NOTICE:  aarray1 is {1,2,3,4,5}
NOTICE:  aarray2 is {101,102,103,104,105}
DO

同样地,上述示例也可以直接在DECLARE段中使用,示例如下,两者预期输出一致。

DECLARE
    TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);  -- 声明 associative array 全局类型
    FUNCTION get_array(aarray IN OUT aarray_type) RETURN aarray_type IS
        i INT;
    BEGIN
        FOR i IN 1..5 LOOP
            aarray(i) := i + 100;
        END LOOP;
        RETURN aarray;
    END;
    aarray1 aarray_type;
    aarray2 aarray_type;
BEGIN
    aarray2 := get_array(aarray1);
    RAISE NOTICE 'aarray1 is %', aarray1;  -- 取值
    RAISE NOTICE 'aarray2 is %', aarray2;  -- 取值
    aarray1(1) := 1;
    aarray1(2) := 2;
    aarray1(3) := 3;
    aarray1(4) := 4;
    aarray1(5) := 5;
    RAISE NOTICE 'aarray1 is %', aarray1;  -- 取值
    RAISE NOTICE 'aarray2 is %', aarray2;  -- 取值
END;

关联数组用作函数参数

关联数组用作函数参数时,IN参数在函数/存储过程内部不可修改,OUT参数在函数/存储过程内部可修改。示例如下:

  • 关联数组用作IN参数

    DECLARE
        TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);
        PROCEDURE set_array(aarray IN aarray_type) IS
            i INT;
        BEGIN
            FOR i IN 1..5 LOOP
                aarray(i) := i;
            END LOOP;
        END;
        aarray aarray_type;
    BEGIN
        set_array(aarray);
    END;

    返回结果如下:

    ERROR:  variable "aarray" is declared CONSTANT
  • 关联数组用作OUT参数

    DECLARE
        TYPE aarray_type IS TABLE OF INT INDEX BY VARCHAR(10);
        PROCEDURE set_array(aarray OUT aarray_type) IS
            i INT;
        BEGIN
            FOR i IN 1..5 LOOP
                aarray(i) := i;
            END LOOP;
        END;
        aarray aarray_type;
    BEGIN
        set_array(aarray);
        RAISE NOTICE '%', aarray;
    END;

    返回结果如下:

    NOTICE:  {1,2,3,4,5}
    DO