PL/SQL中如何获取存储过程返回的refcursor行数(无需全列Fetch)
获取Oracle存储过程返回的Refcursor行数(无需指定所有列)
问题描述
我有一个存储过程Customer_sp,调用语句为Customer_sp(p_musterino=>1111,p_rc1 => p_rc1, p_rc2 => p_rc2, p_rc3 => p_rc3),该存储过程会返回3个独立的REF CURSOR。我需要获取第一个游标rc1返回的行数,rc1的数据来自多表关联,包含大量列,不想为了统计行数而编写包含所有列的FETCH语句,请问是否有简便方法?
方法1:使用BULK COLLECT批量收集到集合
利用PL/SQL的批量收集特性,无需指定具体列,只需定义与游标返回类型匹配的记录集合,一次性获取所有行后通过集合的COUNT属性得到行数:
DECLARE p_rc1 SYS_REFCURSOR; p_rc2 SYS_REFCURSOR; p_rc3 SYS_REFCURSOR; -- 定义与rc1返回结构匹配的记录和集合类型 TYPE rc1_rec_type IS RECORD; TYPE rc1_tab_type IS TABLE OF rc1_rec_type; rc1_result rc1_tab_type; row_count NUMBER; BEGIN -- 调用存储过程获取游标 Customer_sp(p_musterino=>1111, p_rc1 => p_rc1, p_rc2 => p_rc2, p_rc3 => p_rc3); -- 批量收集所有行到集合,无需指定列 FETCH p_rc1 BULK COLLECT INTO rc1_result; -- 获取行数 row_count := rc1_result.COUNT; DBMS_OUTPUT.PUT_LINE('rc1返回的行数:' || row_count); -- 关闭所有游标 CLOSE p_rc1; CLOSE p_rc2; CLOSE p_rc3; END; /
方法2:使用DBMS_SQL工具处理游标
通过DBMS_SQL包将REF CURSOR转换为原生游标,无需解析列结构即可获取行数,适合大数据量场景:
DECLARE p_rc1 SYS_REFCURSOR; p_rc2 SYS_REFCURSOR; p_rc3 SYS_REFCURSOR; dbms_sql_cur NUMBER; row_count NUMBER; BEGIN Customer_sp(p_musterino=>1111, p_rc1 => p_rc1, p_rc2 => p_rc2, p_rc3 => p_rc3); -- 将REF CURSOR转换为DBMS_SQL游标ID dbms_sql_cur := DBMS_SQL.TO_CURSOR_NUMBER(p_rc1); -- 执行获取操作,LAST_ROW_COUNT返回总行数 DBMS_SQL.FETCH_ROWS(dbms_sql_cur); row_count := DBMS_SQL.LAST_ROW_COUNT; DBMS_OUTPUT.PUT_LINE('rc1返回的行数:' || row_count); -- 关闭游标 DBMS_SQL.CLOSE_CURSOR(dbms_sql_cur); CLOSE p_rc2; CLOSE p_rc3; END; /
补充说明
- 方法1适合数据量不大的场景,批量收集会将所有数据加载到内存,若数据量极大可能引发内存问题;
- 方法2通过
DBMS_SQL底层处理,无需加载全部数据到内存,性能更优; - 若有权限修改存储过程,也可以在存储过程内部先统计
rc1对应查询的行数,新增一个输出参数返回行数,这是最直接的方案。
内容的提问来源于stack exchange,提问作者EHan
相关产品推荐
相关产品推荐

