oracle集合一 关联数组(索引表)学习

发布于:2025-06-29 ⋅ 阅读:(21) ⋅ 点赞:(0)

联合数组(索引表)

只能在PL/SQL中使用

数据结构 链式哈希表

语法
TYPE table_type_name IS TABLE OF datatype [ NOT NULL ] INDEX BY index_type;

datatype 可以是标量数据类型、%TYPE引用类型、ROWTYPE引用类型

NOT NULL:如果指定了,那么表中的每一行都必须要有一个值

index_type  是用来组织集合内容索引的数据类型

数值类型 NUMBER子类
BINARY_INTEGER        (-2³¹ 到 2³¹-1)  早期类型,后续版本与PLS_INTEGER 数据结构一致,兼容前版本
子类型
NATURAL               (0 到 2³¹-1)
POSITIVE              (1 到 2³¹-1)

PLS_INTEGER           (-2³¹ 到 2³¹-1)
子类型
NATURALN               (0 到 2³¹-1)
POSITIVEN             (1 到 2³¹-1)
SIGNTYPE               -1, 0 或 1

字符类型
VARCHAR2
NVARCHAR2
VARCHAR
STRING
CHAR
NCHAR
ROWID
UROWID

核心时间复杂度

按键随机查找    O(1)
顺序遍历        O(n)
插入元素        O(1)
删除元素        O(1)


是否需要初始化            不需要
是否空间预分配            不需要EXTEND预分配空间,会(动态扩展)


生命周期
在 DECLARE 时     结束级销毁
子程序局部变量      过程/函数执行期间,子程序执行完毕时销毁
包变量                    整个数据库会话期间,会话结束或包被重新编译时销毁

基础使用(只能在PL/SQL中)

set serveroutput on;
DECLARE
  --定义dict_type 类型为联合数组
  TYPE dict_type IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
  --声明v_dict 为dict_type类型
  v_dict dict_type;
  --不需要初始化,内存动态扩展
BEGIN
  v_dict(1) := 'value1';
  DBMS_OUTPUT.PUT_LINE(v_dict(1));
END;
/

DECLARE
  TYPE emp_map IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
  v_emps emp_map;
  v_key PLS_INTEGER;
BEGIN
  -- 填充数据
  SELECT * BULK COLLECT INTO v_emps FROM employees;
  
  -- 直接遍历联合数组
  v_key := v_emps.FIRST;
  WHILE v_key IS NOT NULL LOOP
    IF v_emps(v_key).salary > 10000 THEN
      DBMS_OUTPUT.PUT_LINE(v_emps(v_key).last_name || ': ' || v_emps(v_key).salary);
    END IF;
    v_key := v_emps.NEXT(v_key);
  END LOOP;
END;

元素操作

方法/操作        语法示例                    描述                时间复杂度
赋值            arr(key) := value            插入或更新元素            O(1)
读取            value := arr(key)            获取元素值                O(1)
删除单个元素    arr.DELETE(key)                移除指定键的元素        O(1)
删除所有元素    arr.DELETE                    清空整个数组            O(n)

属性/方法        语法示例                        描述
EXISTS            IF arr.EXISTS(key)THEN ...        检查指定键是否存在(返回BOOLEAN)
COUNT            num := arr.COUNT                返回当前元素数量
FIRST            key := arr.FIRST                返回第一个(最小)键值
LAST            key := arr.LAST                    返回最后一个(最大)键值
NEXT            key := arr.NEXT(current_key)    返回大于指定键的下一个键
PRIOR            key := arr.PRIOR(current_key)    返回小于指定键的上一个键
LIMIT            max := arr.LIMIT                仅VARRAY有效,返回最大容量(联合数组始终返回NULL)


数据类型转换
函数            示例                            描述
CAST            CAST(arr AS other_type)            类型转换(需兼容类型)
TO_CHAR            TO_CHAR(arr(key))                元素值转为字符串
TO_NUMBER        TO_NUMBER(arr(key))                元素值转为数字

能否直接查询

不能直接查询,可在PL/SQL间接
SELECT * FROM TABLE(v_sql_emps) WHERE salary > 5000
不能在SQL中查询一个函数返回值为联合数组的对象,联合数组只在PL/SQL中生效,如需操作可先转换为嵌套表或可变数组


嵌套关联数组,类似于多维数组

DECLARE
  TYPE phone_array IS TABLE OF VARCHAR2(15)
    INDEX BY VARCHAR2(10);  -- 电话类型到号码的映射
  
  TYPE contact_array IS TABLE OF phone_array
    INDEX BY VARCHAR2(100);  -- 联系人名称到电话数组的映射
    
  v_contacts contact_array;
BEGIN
  -- 添加联系人信息
  v_contacts('John Doe')('Mobile') := '123-456-7890';
  v_contacts('John Doe')('Home') := '234-567-8901';
  v_contacts('Jane Smith')('Work') := '345-678-9012';
  
  -- 遍历嵌套数组
  DECLARE
    v_name VARCHAR2(100);
    v_phone_type VARCHAR2(10);
  BEGIN
    v_name := v_contacts.FIRST;
    WHILE v_name IS NOT NULL LOOP
      DBMS_OUTPUT.PUT_LINE('Contact: ' || v_name);
      v_phone_type := v_contacts(v_name).FIRST;
      WHILE v_phone_type IS NOT NULL LOOP
        DBMS_OUTPUT.PUT_LINE('  ' || v_phone_type || ': ' || v_contacts(v_name)(v_phone_type));
        v_phone_type := v_contacts(v_name).NEXT(v_phone_type);
      END LOOP;
      v_name := v_contacts.NEXT(v_name);
    END LOOP;
  END;
END;