Попытка заменить dbms_xmlgen.xmlget на sys_xmlagg - PullRequest
1 голос
/ 23 декабря 2011

Я работаю над параметризацией некоторых запросов JDBC к Oracle 10gR2.

Большинство запросов имеют форму:

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 вместо пустого документа.

1 Ответ

1 голос
/ 27 января 2012

В данный момент у меня нет доступа к БД Oracle, поэтому, пожалуйста, прости неточности.

Похоже, что параметризация вызова DBMS_XMLGEN является целью.Это достигается с помощью небольшого PL / SQL. Документы Oracle для пакета DBMS_XMLGEN описывают несколько операций, которые должны помочь.Сначала создайте контекст из 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;
...