Oracle 12c 不支持“隐式结果集”这一术语,实际对应的是DBMS_SQL.RETURN_RESULT;该函数需先OPEN SYS_REFCURSOR再显式调用,由客户端驱动(如JDBC需设includeImplicitCursors=true)识别并自动接收结果集,RETURN_RESULT内部自动关闭游标,不兼容自治事务。

Oracle 12c 不支持“隐式结果集”这个概念——你真正想用的是 DBMS_SQL.RETURN_RESULT,它能让 PL/SQL 过程直接把游标结果推给客户端,无需 REF CURSOR 参数声明。
为什么不能用“隐式结果集”这个词
“隐式结果集”是 MySQL 5.7+ 的术语(SELECT 在存储过程中自动返回),Oracle 没有同名机制。12c 引入的是 DBMS_SQL.RETURN_RESULT,它是显式调用、显式推送的,但对客户端来说“看起来像隐式”,因为不用定义 OUT SYS_REFCURSOR 参数。
- 误写成“隐式结果集”会导致搜不到正确文档,也容易和 Oracle 自己的“隐式游标(SQL%ROWCOUNT)”混淆
- 该功能依赖 Oracle Client 12.1+ 和 JDBC 12.1.0.2+ / ODP.NET 12.1+,旧驱动会静默忽略或报 ORA-29481
- 必须在 PL/SQL 块内用
OPEN ... FOR先打开游标,再传给RETURN_RESULT;不能直接RETURN_RESULT(SELECT ...)
DBMS_SQL.RETURN_RESULT 的最小可行写法
以下是一个能跑通的匿名块示例,不带参数、不建过程,直击核心逻辑:
DECLARE c1 SYS_REFCURSOR; BEGIN OPEN c1 FOR SELECT employee_id, last_name FROM employees WHERE rownum
-
DBMS_SQL.RETURN_RESULT只接受已打开的SYS_REFCURSOR,不能传集合、不能传静态 SQL 字符串 - 一个 PL/SQL 执行单元最多可调用 100 次
RETURN_RESULT,每次推送一个结果集(适合多表分页导出场景) - 游标打开后不必
CLOSE——RETURN_RESULT内部会自动关闭,手动关会报 ORA-01001
和传统 REF CURSOR OUT 的关键区别
对比你可能熟悉的三参数存储过程写法:
CREATE OR REPLACE PROCEDURE get_emps(p_out OUT SYS_REFCURSOR) AS BEGIN OPEN p_out FOR SELECT * FROM employees; END;
-
REF CURSOR OUT要求调用方显式声明变量、绑定参数、循环读取DataReader.NextResult()—— C# 或 Java 层代码更重 -
DBMS_SQL.RETURN_RESULT把结果“喷出来”,客户端收到的就是第一个(或第 N 个)结果集,ExecuteNonQuery()就能触发,无需额外参数绑定 - 无法在调用
RETURN_RESULT后再对同一游标做FETCH或CLOSE,否则报 ORA-29481(“result set already returned”) - 事务控制仍由外部决定:如果过程里做了 DML,
RETURN_RESULT不影响提交时机
容易被忽略的兼容性陷阱
这个功能看着简单,但上线前必须确认三点:
- 客户端工具是否识别:SQL*Plus 12.1+ 默认开启,但需执行
SET SERVEROUTPUT OFF避免干扰;SQL Developer 要在 Preferences → Database → Worksheet → “Show output from DBMS_OUTPUT and implicit results” 打钩 - JDBC 必须启用隐式结果支持:
connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT)不够,得加props.setProperty("oracle.jdbc.includeImplicitCursors", "true") - 不能嵌套在自治事务(
PRAGMA AUTONOMOUS_TRANSACTION)里用RETURN_RESULT,否则报 ORA-06519(自治事务中不允许返回结果集)
真正麻烦的从来不是语法本身,而是客户端驱动版本和配置开关——写对了 PL/SQL,却在 Java 层收不到结果,八成是漏了 includeImplicitCursors 这个开关。











