【问题标题】:Trying to replace dbms_xmlgen.xmlget with sys_xmlagg试图用 sys_xmlagg 替换 dbms_xmlgen.xmlget
【发布时间】:2011-12-22 22:41:53
【问题描述】:

我正在针对 Oracle 10gR2 参数化一些 JDBC 查询。

大部分查询的格式如下:

String value = "somevalue";
String query = "select dbms_xmlgen.xmlget('select c1, c2 from t1 where c1 = ''"
    + somevalue + "'' ') xml from dual;";

我无法按原样对其进行参数化,因为实际选择位于 xmlget 内的带引号的字符串中,并且参数未在字符串内展开。 JDBC 会将该查询视为没有参数。

我在模仿dbms_xmlgen.xmlget 的行为方面相当成功:

String query = "SELECT xmltype.getclobval(sys_xmlagg(xmlelement(\"ROW\","                                                                                        
    + "xmlforest(c1, c2)))) xml from t1 where c1 = ?";

我无法解决的唯一问题是查询不返回任何行的情况。

使用dbms_xmlgen.xmlget,没有行会返回空的 CLOB。但是,对于 sys_xmlagg,没有行会导致 CLOB 包含:

<?xml version="1.0"?><ROWSET></ROWSET>

我正在寻找一种解决方案,它会给我一个空的 CLOB 而不是一个空的文档。

【问题讨论】:

    标签: sql xml oracle sqlxml


    【解决方案1】:

    我目前无法访问 Oracle 数据库,因此请原谅不准确之处。

    DBMS_XMLGEN 调用的参数化似乎是目标。这是通过使用一点 PL/SQL 来完成的。 The Oracle Docs for the DBMS_XMLGEN package 描述了一些应该有帮助的操作。首先,使用这种形式从 SYS_REFCURSOR 创建一个上下文:

    DBMS_XMLGEN.NEWCONTEXT (
      queryString  IN SYS_REFCURSOR)
    RETURN ctxHandle;
    

    然后,以GetXML的另一种形式使用上下文:

    DBMS_XMLGEN.GETXML (
       ctx          IN ctxHandle, 
       tmpclob      IN OUT NCOPY CLOB,
       dtdOrSchema  IN number := NONE)
    RETURN BOOLEAN;
    

    使用这种方法还有可能重用 CLOB(而不是创建一个新的临时的)的好处,这可能有助于提高性能。还有另一种形式,它更像您在示例中使用的形式,但丢失了此属性。

    还有一件事……这个例子中GETXML 的返回应该告诉你是否有返回的行。这应该比在操作完成时检查 CLOB 的内容更可靠。或者,您可以在上下文中使用 NumRowsProcessed 函数来获取 CLOB 中包含的行数。

    您的代码大致如下所示:

    DECLARE
      srcRefCursor SYS_REFCURSOR;
      ctxHandle ctxHandle;
      somevalue VARCHAR2(1000);
      myClob CLOB;
      hasRows boolean;
    BEGIN
      OPEN srcRefCursor FOR
          SELECT c1, c2 
          FROM t1 
          WHERE c1 = somevalue; --Note parameterized value
    
      ctxHandle := DBMS_XMLGEN.NEWCONTEXT(srcRefCursor);
    
      hasRows := DBMS_XMLGEN.GETXML(
          ctxHandle,
          myClob -- XML stored in myCLOB
      );
    
      IF (hasRows) THEN
        /* Do work on CLOB here */
      END IF;
    
    
      DBMS_XMLGEN.CLOSECONTEXT(ctxHandle);
    END;
    

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多