sql - 引用光标在 XMLType.createxml 中丢失

标签 sql oracle cursor xmltype

我正在调用一个返回引用光标的函数,并且我正在使用 XMLType.createxml 将结果转换为 XML,例如

select XMLType.createxml(package_name.storedProcName('PARAM1', 'PARAM2', 'PARAM3')) as sresult from dual;

但是,我发现这有一个不受欢迎的副作用。用于检索 XMLType 数据的游标似乎从未关闭。使用这种技术多次调用该函数后,我总是遇到以下错误:

ORA-01000: maximum open cursors exceeded

我没有光标句柄,因此无法手动关闭它。此外,我们正在使用池连接,因此不会重置连接,从而可以自动释放这些游标。对此可以采取什么措施?


这是我的 Oracle 版本(从 v$version 返回):

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

(对于那些感兴趣的人,here is a link 我之前与 XMLType 相关的问题。)

最佳答案

似乎存在错误,您应该向 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

使用上述函数调用时,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

您应该能够使用包装函数来防止 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

关于sql - 引用光标在 XMLType.createxml 中丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15479135/

相关文章:

SQL TOP 1 在子查询中使用时返回 null

c# - 展平具有未知列数的子/父数据

sql - 无法合并联合所有 View

SQL解析数字数据的列字符串并存储在单独的列中

MySQL存储过程在不使用游标的情况下迭代多个值返回错误代码: 1172.结果由多于一行组成

sql - 按使用 case 表达式内的别名的计算列进行排序

sql - Firebird 外部表

java - 如何用Java查看Oracle数据库的执行计划

sql - Oracle中的游标循环