DBMS_SQL.RETURN_RESULT是Oracle 12c引入的隐式结果集返回机制,用于跳过OUT SYS_REFCURSOR参数绑定,直接将已打开游标推送给兼容客户端;它不提升性能、不替代动态SQL执行、不支持分页或嵌套调用,仅简化T-SQL迁移场景下的多结果集输出。
oracle12c 的不是“更好用”,而是解决了一个具体迁移痛点:让 pl/sql 存储过程能像 sql server 的 t-sql 那样隐式返回多个结果集,无需客户端预先声明参数。
DBMS_SQL.RETURN_RESULT 是什么,不是什么
它不是替代
包的通用动态 SQL 执行能力,也不是增强性能的机制。它只是一个“结果投递开关”——只负责把已打开的
实例直接推给客户端,跳过传统 OUT 参数绑定流程。
不改变游标打开逻辑:仍需
,只是后续不用
或
声明
不支持流式或分页控制:整个结果集一次性发送,无法暂停、跳过或限制行数
不兼容老客户端:SQL*Plus 12c+、JDBC 12.1+、ODP.NET 12.1+ 才识别隐式结果;11g 客户端连上 12c 数据库也收不到
不能嵌套调用:不能在另一个
游标执行过程中调用它;它只作用于当前 PL/SQL 执行上下文
为什么从 T-SQL 迁移时它显得“更简单”
因为 T-SQL 存储过程中允许裸写
,客户端自动接收结果集。而 Oracle 11g 及之前必须显式定义
,客户端还得逐个
绑定——这在 Java/.NET 中容易漏配、顺序错乱、类型不匹配。
迁移旧 T-SQL 过程时,只需把
包进
+
,不用改调用方代码结构
一个过程可发多个结果集,
在 JDBC 中对应
,比维护多个命名游标更线性
避免了游标变量名冲突问题:传统方式中多个
参数必须重命名(
,
),而隐式方式只管开、不管名
但注意:SQL*Plus 中会按执行顺序编号显示
、
,没有别名,调试时靠位置判断
GaussDB 等不支持该特性的数据库怎么应对
不是“降级写法”,而是回归 Oracle 11g 兼容模式:用明确的
参数替代隐式返回。关键点不在语法,而在调用链适配。
oracle知识库
oracle知识库下载
下载
存储过程签名必须修改:增加带唯一名字的
参数,如
、
原
行直接删掉或注释,改为
客户端代码必须同步更新:JDBC 需要
并按序调用
不能复用同名变量:GaussDB 不支持
多次
后反复
,所以每个结果集必须配独立游标变量和 OUT 参数
真正容易被忽略的是客户端兼容性边界——
看似简化了服务端,实则把适配压力转移到了驱动层和应用层。一旦跨数据库迁移,别只盯着存储过程改写,先确认你用的 JDBC 版本、连接池配置、ORM 框架是否识别隐式结果集。否则过程编译通过,运行时却拿不到任何结果。
dbms_sql.return_resultout sys_refcursorDBMS_SQLSYS_REFCURSOROPEN l_cursor FOR ...RETURN l_cursorOUTDBMS_SQLSELECTOUT SYS_REFCURSORregisterOutParameter(..., Types.OTHER)SELECT ...OPEN ... FORDBMS_SQL.RETURN_RESULTDBMS_SQL.GET_NEXT_RESULTResultSet.nextResult()OUTrc1rc2ResultSet #1ResultSet #2OUT SYS_REFCURSOROUTp_emp_result OUT SYS_REFCURSORp_dept_result OUT SYS_REFCURSORDBMS_SQL.RETURN_RESULT(l_cursor)OPEN p_emp_result FOR SELECT ...CallableStatement.registerOutParameter(2, Types.OTHER)getResultSet()l_cursorOPENRETURN_RESULTDBMS_SQL.RETURN_RESULT