最佳实践

Halo数据库关联数组功能演示

D
DBA 团队
2023年10月17日

关联数组是一种将唯一键与值相关联的集合。键不必是数字,也可以是字符数据。本文将简单展示一下 Halo 数据库中新增的关联数组相关功能。

一、语法定义

如果指定了 INDEX BY BINARY_INTEGER 或 PLS_INTEGER,则键可以是任何负整数、正整数或零。如果指定了 INDEX BY VARCHAR2,则键可以是字符数据。

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

• assoctype 是分配给数组类型的标识符,后续根据此标识符创建关联数组变量。 • datatype 是标量数据类型,例如 VARCHAR2 或 NUMBER。 • rectype 是先前定义的记录类型。 • objtype 是先前定义的对象类型。 • n 是字符键的最大长度。

二、相关方法演示

2.1、FIRST

FIRST 是一个返回集合中第一个元素的下标的方法。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('FIRST element: ' || arr.FIRST);
END;
/

2.2、LAST

LAST 是一个返回集合中最后一个元素的下标的方法。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('LAST element: ' || arr.LAST);
END;
/

2.3、COUNT

COUNT 是一种返回集合中元素数量的方法。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('COUNT: ' || arr.COUNT);
END;
/

2.4、NEXT

NEXT 是一个返回指定下标后面的下标的方法。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('NEXT element: ' || arr.NEXT('arr4'));
END;
/

2.5、PRIOR

PRIOR 方法返回集合中指定下标前面的下标。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('PRIOR element: ' || arr.PRIOR('arr2'));
END;
/

2.6、EXISTS

EXISTS 方法验证集合中是否存在指定下标。如果存在则返回 TRUE,否则返回 FALSE。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('The index exists: ' ||
        CASE WHEN arr.EXISTS('arr5') = TRUE THEN 'true' ELSE 'false' END || ' arr5');
    DBMS_OUTPUT.PUT_LINE('The index exists: ' ||
        CASE WHEN arr.EXISTS('arr6') = TRUE THEN 'true' ELSE 'false' END || ' arr6');
END;
/

2.7 DELETE

DELETE 方法删除集合中的条目。此处演示删除指定位置的数组元素。

sql
DECLARE
    TYPE arr_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(50);
    arr arr_typ;
BEGIN
    arr('arr1') := -100;
    arr('arr2') := -10;
    arr('arr3') := 0;
    arr('arr4') := 10;
    arr('arr5') := 100;
    DBMS_OUTPUT.PUT_LINE('COUNT: ' || arr.COUNT);
    DBMS_OUTPUT.PUT_LINE('The index exists: ' ||
        CASE WHEN arr.EXISTS('arr3') = TRUE THEN 'true' ELSE 'false' END || ' arr3');
    arr.DELETE('arr3');
    DBMS_OUTPUT.PUT_LINE('The index exists: ' ||
        CASE WHEN arr.EXISTS('arr3') = TRUE THEN 'true' ELSE 'false' END || ' arr3');
    DBMS_OUTPUT.PUT_LINE('COUNT: ' || arr.COUNT);
END;
/

三、综合演示

接下来让我们结合上面的内容,简单组合一下,写一段测试 SQL 看看。

sql
-- 创建一个复合类型
CREATE TYPE ob_type_test AS OBJECT (
    col_a VARCHAR2(50),
    col_b VARCHAR2(50),
    col_c VARCHAR2(50)
);

DECLARE 
    TYPE arr_typ IS TABLE OF ob_type_test INDEX BY VARCHAR2(50);
    TYPE arr_typ2 IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
    arr arr_typ;
    var_a ob_type_test;
    var_b VARCHAR(50);
BEGIN
    -- 复合类型赋值
    var_a.col_a := 'a';
    var_a.col_b := 'b';
    var_a.col_c := 'c';

    -- 构造关联数组数据
    FOR i IN 1 .. 5 LOOP
        arr('arr'||i) := var_a;
        var_a.col_a := var_a.col_a || 'x';
        var_a.col_b := var_a.col_b || 'x';
        var_a.col_c := var_a.col_c || 'x';
    END LOOP;

    RAISE NOTICE '----------------------------';
    -- 正序遍历
    var_b := arr.FIRST;
    WHILE var_b IS NOT NULL LOOP
        RAISE NOTICE '% % % %', var_b, arr(var_b).col_a, arr(var_b).col_b, arr(var_b).col_c;
        var_b := arr.NEXT(var_b);
    END LOOP;

    RAISE NOTICE '----------------------------';
    -- 逆序遍历
    var_b := arr.LAST;
    WHILE var_b IS NOT NULL LOOP
        RAISE NOTICE '% % % %', var_b, arr(var_b).col_a, arr(var_b).col_b, arr(var_b).col_c;
        var_b := arr.PRIOR(var_b);
    END LOOP;

    RAISE NOTICE '----------------------------';
    -- 打印元素数量
    RAISE NOTICE 'count: %', arr.COUNT;

    -- 删除元素 arr3
    arr.DELETE('arr3');
    RAISE NOTICE 'count2: %', arr.COUNT;

    RAISE NOTICE '----------------------------';
    -- 判断 arr0 到 arr8 是否存在
    FOR i IN 0 .. 8 LOOP
        IF arr.EXISTS('arr'||i) THEN 
            RAISE NOTICE '% exists', 'arr'||i;
        ELSE 
            RAISE NOTICE '% is not exists', 'arr'||i;
        END IF;
    END LOOP;

    RAISE NOTICE '----------------------------';
    -- 清空整个数组
    arr.DELETE;
    RAISE NOTICE 'count3: %', arr.COUNT;
    RAISE NOTICE '----------------------------';
END;

运行结果如下:


最新文章

安全公告
2025年04月11日

羲和(Halo)数据库关键补丁更新公告 - 2025年4月

安全公告
2024年06月20日

羲和(Halo)数据库关键补丁更新公告 - 2024年6月

安全公告
2023年12月18日

羲和(Halo)数据库关键补丁更新公告 - 2023年12月