where current of 仅在oracle pl/sql块中配合显式for update游标使用,用于更新游标当前行;须先open、fetch,再update/delete where current of,且不可在fetch后commit或游标未声明for update。

WHERE CURRENT OF 只在 Oracle 中有效,且必须配合显式 FOR UPDATE 游标 + PL/SQL 块内循环使用;裸 SQL 或匿名块外直接写会报 ORA-01001 或 ORA-01002。
Oracle 中 WHERE CURRENT OF 的合法使用场景
它不是独立语句,而是 UPDATE / DELETE 的子句,作用是“更新游标当前指向的那行原始数据”。只在 PL/SQL 块中、显式游标已打开、FETCH 已执行、且游标声明含 FOR UPDATE 时才生效。
- 必须用
CURSOR ... IS SELECT ... FOR UPDATE声明游标(不能是隐式游标或未加FOR UPDATE的显式游标) - 必须在 PL/SQL 块内使用(比如
DECLARE ... BEGIN ... END;),不能在 SQL*Plus 直接执行UPDATE ... WHERE CURRENT OF - 必须先
OPEN游标,再FETCH一行,然后立即UPDATE ... WHERE CURRENT OF cursor_name—— 中间不能有COMMIT、INSERT、调用过程等干扰 - 游标变量名必须和
WHERE CURRENT OF后的名称完全一致(大小写敏感,若未加双引号)
常见错误:ORA-01001 invalid cursor 和 ORA-01002 fetch out of sequence
这两个错误几乎都源于游标生命周期管理不当:
-
ORA-01001:游标没OPEN就 FETCH,或已CLOSE还继续用;也可能是游标名拼错,比如声明为my_cur却写成WHERE CURRENT OF my_cursor -
ORA-01002:在FETCH后执行了COMMIT或ROLLBACK,导致游标失效;或者FETCH到末尾后还继续FETCH,再试图WHERE CURRENT OF - 漏掉
FOR UPDATE不一定立刻报错,但WHERE CURRENT OF会静默失败(更新 0 行),且不加锁,失去定位更新意义
正确写法示例(带 NOWAIT 避免锁等待)
DECLARE
CURSOR c_emp IS
SELECT empno, sal FROM emp WHERE deptno = 20 FOR UPDATE OF sal NOWAIT;
r_emp c_emp%ROWTYPE;
BEGIN
OPEN c_emp;
LOOP
FETCH c_emp INTO r_emp;
EXIT WHEN c_emp%NOTFOUND;
<pre class="brush:php;toolbar:false;">IF r_emp.sal < 3000 THEN
UPDATE emp SET sal = sal + 200 WHERE CURRENT OF c_emp;
END IF;END LOOP; COMMIT; -- 必须在循环结束后统一提交 CLOSE c_emp; END;
注意:NOWAIT 能防止因其他会话锁住某行而无限等待;COMMIT 放在循环外,否则下一次 FETCH 就会触发 ORA-01002;c_emp%ROWTYPE 确保结构匹配,避免列顺序/类型错位。
替代方案往往更安全、更高效
真要逐行判断再更新,WHERE CURRENT OF 不是唯一选择,而且容易引入锁竞争和维护成本。多数情况可用集合操作代替:
- 单次批量更新:
UPDATE emp SET sal = sal + 200 WHERE deptno = 20 AND sal - 需分批控制并发量:
UPDATE emp SET sal = sal + 200 WHERE empno IN (SELECT empno FROM (SELECT empno FROM emp WHERE deptno = 20 AND sal - 需要复杂逻辑(如调用函数、日志记录):改用
BULK COLLECT+FORALL,把数据拉到内存处理,再批量 DML
硬套 WHERE CURRENT OF 的代价常被低估:它让每行更新都持锁、串行执行、难以并行、调试困难 —— 除非业务强依赖“取一行 → 判断 → 更新该行 → 再取下一行”的原子性流程,否则优先走集合路径。











