关联数组是一种将唯一键与值相关联的集合。键不必是数字,也可以是字符数据。本文将简单展示一下 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;运行结果如下:
