显式游标必须用 CURSOR 关键字声明,因其是命名、可复用的对象,需配合 OPEN/FETCH/CLOSE 手动控制;仅写 SELECT 触发隐式游标,无法手动管理。
显式游标声明时为什么必须用 CURSOR 关键字而不是直接写查询?
因为 pl/sql 要求显式游标是命名的、可复用的数据库对象,不是一次性的结果集。只写 select ... 是隐式游标行为,无法手动控制 open/fetch/close 流程。
声明必须带名字和 IS(或 AS),后面跟完整查询语句:
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees WHERE department_id = 10;
-
CURSOR后的名字是标识符,不能加引号,也不能和变量同名 - 查询里不能有分号,否则编译报错:
PLS-00103: Encountered the symbol ";" - 声明阶段不执行查询,只是定义;真正执行在
OPEN时
OPEN 之后不 FETCH 就 CLOSE 会怎样?
语法上完全合法,但毫无意义——游标打开后没取数据就关闭,等于白开一次。更危险的是:如果后续忘了 OPEN 就直接 FETCH,会触发运行时错误:ORA-01001: invalid cursor。
- 必须严格遵循
OPEN → FETCH → CLOSE顺序,中间不能跳步 -
FETCH每次只取一行(除非用BULK COLLECT),多次FETCH才能遍历全部结果 - 建议总把
FETCH放在循环里,并用%NOTFOUND判断结束,而不是靠行数硬编码
为什么 FETCH 必须搭配 INTO 变量且类型要严格匹配?
因为 FETCH 不是返回结果集,而是把当前游标行的字段值“拷贝”进你指定的变量里。类型不一致会导致运行时报错:ORA-06502: PL/SQL: numeric or value error。
-
INTO后的变量个数、顺序、数据类型必须和游标查询字段完全一致 - 比如游标查了
employee_id NUMBER和last_name VARCHAR2(25),INTO就得用一个NUMBER变量 + 一个长度 ≥25 的VARCHAR2变量 - 可以用记录类型简化:
emp_rec employees%ROWTYPE,然后FETCH emp_cursor INTO emp_rec
忘记 CLOSE 游标会引发什么实际问题?
短期看可能没异常,但长期会耗尽会话级游标资源,最终触发:ORA-01000: maximum open cursors exceeded。这个限制由初始化参数 open_cursors 控制,默认常为 300,很难临时调高。
- 即使发生异常退出,也要确保
CLOSE执行——所以推荐用EXCEPTION块兜底,或直接用FOR循环隐式管理(它自动OPEN/FETCH/CLOSE) -
CLOSE已关闭的游标不会报错,但重复OPEN未关闭的游标会报:ORA-06511: PL/SQL: cursor already open - 真正容易被忽略的是:子程序里打开的游标,调用方无法感知是否已关——必须文档化或强制在子程序末尾
CLOSE

















