1

我正在针对 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 而不是一个空的文档。

4

1 回答 1

1

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

调用的参数化DBMS_XMLGEN似乎是目标。这是通过使用一点 PL/SQL 来完成的。DBMS_XMLGEN 包的 Oracle 文档描述了一些应该有帮助的操作。首先,使用以下形式从 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;
于 2012-01-27T19:11:41.450 回答