oracle集合一 关联数组(索引表)学习
联合数组(索引表)
只能在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;--不需要初始化,内存动态扩展
BEGINv_dict(1) := 'value1';DBMS_OUTPUT.PUT_LINE(v_dict(1));
END;
/DECLARETYPE 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 LOOPIF v_emps(v_key).salary > 10000 THENDBMS_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中生效,如需操作可先转换为嵌套表或可变数组
嵌套关联数组,类似于多维数组
DECLARETYPE phone_array IS TABLE OF VARCHAR2(15)INDEX BY VARCHAR2(10); -- 电话类型到号码的映射TYPE contact_array IS TABLE OF phone_arrayINDEX 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';-- 遍历嵌套数组DECLAREv_name VARCHAR2(100);v_phone_type VARCHAR2(10);BEGINv_name := v_contacts.FIRST;WHILE v_name IS NOT NULL LOOPDBMS_OUTPUT.PUT_LINE('Contact: ' || v_name);v_phone_type := v_contacts(v_name).FIRST;WHILE v_phone_type IS NOT NULL LOOPDBMS_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;