Ste*_*han 2 sql oracle cursor xmltype
我正在调用一个返回引用游标的函数,我XMLType.createxml用来将结果转换为XML,例如
select XMLType.createxml(package_name.storedProcName('PARAM1', 'PARAM2', 'PARAM3')) as sresult from dual;
Run Code Online (Sandbox Code Playgroud)
但是,我发现这有一个不受欢迎的副作用.似乎用于检索XMLType数据的游标永远不会关闭.使用这种技术多次调用函数后,我总是遇到以下错误:
ORA-01000: maximum open cursors exceeded
Run Code Online (Sandbox Code Playgroud)
我没有光标的句柄,因此我无法手动关闭它.此外,我们使用池化连接,因此没有连接重置可以自动释放这些游标.关于这个还能做什么?
这是我的Oracle版本(从v $版本返回):
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production
CORE 10.2.0.5.0 Production
TNS for HPUX: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production
Run Code Online (Sandbox Code Playgroud)
似乎有一个错误,您应该向Oracle支持打开服务请求.我将发布一个测试用例,在9i和11.2.0.3中重现你的发现:
SQL> SHOW parameter open_cursors
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
open_cursors integer 600
SQL> CREATE OR REPLACE FUNCTION ret_cursor RETURN SYS_REFCURSOR IS
2 l SYS_REFCURSOR;
3 BEGIN
4 OPEN l FOR
5 SELECT * FROM dual;
6 RETURN l;
7 END;
8 /
Function created
Run Code Online (Sandbox Code Playgroud)
使用上述函数调用时,XMLType不会正确关闭游标,而它与静态SQL一起使用时效果很好:
SQL> /* Works as expected with static cursor */
2 DECLARE
3 l XMLTYPE;
4 BEGIN
5 FOR i IN 1 .. 1e4 LOOP
6 SELECT xmltype.createXML(CURSOR(SELECT * FROM DUAL)) INTO l FROM dual;
7 END LOOP;
8 END;
9 /
PL/SQL procedure successfully completed
SQL> /* Fails with call to dynamic cursor */
SQL> DECLARE
2 l XMLTYPE;
3 BEGIN
4 FOR i IN 1 .. 1e4 LOOP
5 SELECT xmltype.createXML(ret_cursor) INTO l FROM dual;
6 END LOOP;
7 END;
8 /
DECLARE
*
ERROR at line 1:
ORA-01000: maximum open cursors exceeded
ORA-06512: at "APPS.RET_CURSOR", line 4
ORA-06512: at line 5
Run Code Online (Sandbox Code Playgroud)
您应该能够使用包装函数来防止ORA-01000发生(在9iR2,11gR2上测试):
SQL> CREATE OR REPLACE FUNCTION wrap_xml(p SYS_REFCURSOR) RETURN XMLTYPE IS
2 l XMLTYPE;
3 BEGIN
4 l := xmltype.CreateXML(p);
5 IF p%ISOPEN THEN
6 CLOSE p;
7 END IF;
8 RETURN l;
9 END;
10 /
Function created
SQL> DECLARE
2 l XMLTYPE;
3 BEGIN
4 FOR i IN 1 .. 1e4 LOOP
5 l := wrap_xml(ret_cursor); -- a SELECT FROM dual will still fail here
6 -- on 9i but not on 11g
7 END LOOP;
8 END;
9 /
PL/SQL procedure successfully completed
Run Code Online (Sandbox Code Playgroud)