尝试使用sys_xmlagg替换dbms_xmlgen.xmlget

时间:2011-12-22 22:41:54

标签: sql xml oracle sqlxml

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

大多数查询的格式为:

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

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

我在使用:{/ p>模仿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而不是一个空文档的解决方案。

1 个答案:

答案 0 :(得分: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(而不是创建新临时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;