Oracle 21c 不存在“迭代游标”,新增的是纯 PL/SQL 的 FOR 循环 iterator 语法(如 VALUES OF、INDICES OF),仅适用于内存集合遍历,不作用于数据库游标,也不能替代 BULK COLLECT + FORALL 或 CURSOR FOR LOOP 等真实游标优化方案。

Oracle 21c 的迭代游标特性本身并不存在——所谓“迭代游标”是误传,实际增强的是 FOR 循环的 iterator 语法,它和游标(CURSOR)无关,也不改变游标行为。
为什么你查不到 CURSOR FOR ... IN VALUES OF 这类写法
官方文档中出现的 values_of_control、indices_of_control 等属于 iteration_control 类型,仅适用于 FOR i IN ... LOOP 这类纯内存迭代,不作用于数据库游标。试图把它们套在 CURSOR FOR 上会直接报错:PLS-00103: Encountered the symbol "VALUES"。
-
FOR emp_rec IN (SELECT * FROM employees)—— 这是传统隐式游标,21c 未改动 -
FOR i IN 1..10 BY 2—— 这是 21c 新增的迭代器语法,纯 PL/SQL 数值/集合遍历 -
FOR i IN VALUES OF my_array—— 合法,但my_array必须是已声明的集合变量(如TABLE或VARRAY),不是游标
VALUES OF 和 INDICES OF 实际能做什么
它们只对 PL/SQL 集合类型生效,本质是把集合遍历逻辑从显式 LOOP + EXTEND + COUNT 中解放出来,写法更紧凑,但**不减少 SQL 执行次数,也不替代游标**。
-
VALUES OF:遍历集合元素值,等价于FOR i IN 1..coll.COUNT LOOP coll(i) -
INDICES OF:遍历集合下标,适合稀疏数组(INDEX BY类型) - 必须提前把数据查到集合里,比如用
BULK COLLECT INTO,否则无法使用 - 示例:
DECLARE TYPE t_ids IS TABLE OF NUMBER; l_ids t_ids; BEGIN SELECT employee_id BULK COLLECT INTO l_ids FROM employees WHERE dept_id = 10; FOR id IN VALUES OF l_ids LOOP UPDATE orders SET status = 'PROCESSED' WHERE emp_id = id; END LOOP; END;
真正影响复杂业务循环性能的关键点
多数人想“重构循环”其实是为解决逐行更新慢、锁等待高、日志膨胀等问题,而 21c 的迭代器语法对此**几乎无改善**。真正起效的是以下组合:
- 用
BULK COLLECT+FORALL替代单条UPDATE:减少上下文切换和网络往返 - 把业务逻辑尽量下沉到单条 SQL(如
MERGE、带子查询的UPDATE),避免 PL/SQL 循环 - 若必须用循环,优先选
CURSOR FOR LOOP而非显式游标(自动管理 OPEN/FETCH/CLOSE,少出错) -
REVERSE或BY step在数值循环中有用,但在处理结果集时毫无意义——数据库返回顺序由ORDER BY控制,不是靠REVERSE倒序遍历游标
最容易被忽略的一点:21c 的 iterator 语法虽简洁,但所有 IN 后的表达式都会被**完全求值后载入内存**。如果 VALUES OF 后跟的是百万级集合,会瞬间吃光 PGA,比传统游标更危险。











