用INDEX BY PLS_INTEGER而非TABLE OF,因其为纯栈上结构、无元数据开销,内存占用仅为后者的1/3~1/5;声明需用TYPE定义+PLS_INTEGER索引,填充应直接赋值(如l_map(1):='A'),禁用EXTEND()以免退化堆分配。
为什么用 INDEX BY PLS_INTEGER 而不是 TABLE OF?
oracle 中的 table of(嵌套表)在声明后默认走堆分配,哪怕只存 5 条 varchar2(100),也会触发内存描述符、分配头、动态堆管理三重开销;而 index by pls_integer 是纯栈上结构,元素直接存值+索引槽,无元数据膨胀。实测在循环内反复构造百条级映射时,后者内存占用可低至前者的 1/3~1/5。
怎么声明和填充才不踩坑?
常见错误是先声明再调用 EXTEND(),比如:
TYPE t_map IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;<br>l_data t_map;<br>l_data.EXTEND(); -- 错!这会让 Oracle 退化为堆分配<br>l_data(1) := 'A';
正确做法是绕过集合方法,直接按需赋值:
- 用明确下标赋值:
l_map(1) := 'active'; l_map(99) := 'pending'; - 下标可以不连续,也不必从 1 开始,
l_map(-5) := 'error'合法且高效 - 避免用
COUNT判断是否为空——空集合COUNT返回 0,但FIRST返回 NULL,更稳妥的判空写法是IF l_map.FIRST IS NULL THEN ...
什么时候该换回嵌套表?
INDEX BY 表不支持 TRIM、DELETE(全删)、CAST 等操作,且无法直接用 SQL 查询(如 SELECT * FROM TABLE(l_map))。所以:
- 缓存几十~几百条静态配置(状态码、国家简码、权限位图)——选
INDEX BY PLS_INTEGER - 需要批量插入数据库、或要参与 SQL 集合操作(
MULTISET、COLLECT)——必须用TABLE OF或VARRAY - 元素数量可能超万、且频繁增删——考虑改用全局临时表(
GTTS),比任何 PL/SQL 集合都更稳
%TYPE 和 PLS_INTEGER 必须一起用
别写 l_id NUMBER := 1; 再塞进 INDEX BY 数组——索引类型不匹配会隐式转换,失去 PLS_INTEGER 的零开销优势。正确模式是:
DECLARE<br> TYPE t_cache IS TABLE OF employees.last_name%TYPE INDEX BY PLS_INTEGER;<br> l_names t_cache;<br>BEGIN<br> l_names(101) := 'King'; -- 下标用 PLS_INTEGER,值类型对齐表字段<br>END;
这里 employees.last_name%TYPE 不仅同步长度,还让 Oracle 编译期确定字符集实际字节数;而 PLS_INTEGER 保证下标运算不触发浮点转换——两者缺一不可。


















