在我们的应用程序中,我们调用各种以下列方式返回引用游标的存储过程:
SELECT foo_package.sp_Bar('arg1', 'arg2', 'arg3', 'arg4') FROM dual;
该wrap_xml
函数所做的是将游标结果转换为 XML 类型,然后将在应用程序中使用。转换后,它立即关闭光标(这一步已经为我们解决了内存问题)。
FUNCTION wrap_xml (c_result SYS_REFCURSOR)
RETURN XMLTYPE
IS
xml_val XMLTYPE;
BEGIN
xml_val := xmltype.CreateXML (c_result);
IF c_result%ISOPEN
THEN
CLOSE c_result;
END IF;
RETURN xml_val;
END;
在大多数情况下,这似乎工作正常:创建 XML 并关闭游标。但是,由于引入了一个为动态查询打开游标的存储过程,我们观察到打开的游标迅速增加,最终导致:
ORA-01000: maximum open cursors exceeded
构建动态查询是为了“模拟”从其他游标返回的结果,用于测试目的。例如,存储过程将构建一个动态查询,如下所示:
SELECT '1' as "COLUMN1", '990' as "COLUMN2", 'N' as "COLUMN3", NULL as "COLUMN5" FROM dual;
然后它将为此查询字符串打开一个游标,并返回游标:
OPEN rc_return FOR v_sql_query;
RETURN rc_return;
生成的参考游标再次传递给wrap_xml
上面的函数,我希望它关闭游标——就像它关闭任何其他游标一样。然而,情况似乎并非如此,因为打开游标的数量一直在增长。这可能是什么原因?
补充调查:
单步执行该wrap_xml
函数,我可以看到程序流程跳过了c_result%ISOPEN
检查的主体,暗示光标确实已关闭。然而,打开的游标数量似乎仍在增加!