Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > Преобразование CLOB -> XMLType


Автор: Plamenk 4.7.2005, 11:11
Всем Привет!

Наткнулся на очень странную ошибку, при преобразовании CLOB -> XMLType в Oracle9i.

У меня есть ХП, куда передается CLOB, который преобразуется следующим кодом в XMLType

Код

XMLType(xmlNew)


Это преобразование иногда работает нормально, а иногда вылетает (так происходит ошибка, когда XML больше 32KB).

И что самое интересное - это лечится следующим кодом

Код

    insert into tmp_clob(data) values (xmlUpd);
    select data into xmlTemp from tmp_clob;
    DELETE FROM tmp_clob;

    XMLType(xmlTemp )


Вопрос: Как решить эту проблему без использования преведенного выше кода?
И из-за чего может возникать данная ошибка?

Заранее Все БОЛЬШОЕ СПАСИБО!

Автор: VIAcom 4.7.2005, 16:02
Plamenk
О у меня была походу такая проблема но когда я читал из CLOB в файл. Собственно это связано с тем, что видимо нельзя обработать сразу весь LOB, а делать это надо по кусочкам не знаю чем вызвано ограничение именно в 1/2 сегмента - Length:=32767;

не уверен, но надеюсь что поможет ...
... нет почти наверняка не поможет

Автор: LSD 4.7.2005, 20:19
Цитата(VIAcom @ 4.7.2005, 17:02)
ограничение именно в 1/2 сегмента - Length:=32767

Это скорее ограничение не 1/2 сегмента, а длинны VARCHAR2 в PL/SQL.

Plamenk
Я полагаю надо работать через DBMS_LOB.CREATETEMPORARY, хотелось бы посмотреть весь код процедуры.

Автор: Plamenk 5.7.2005, 08:05
Спасибо за ответы! Привожу полный текст процедуры:
В данном варианте она всегда нормально отрабатывает, но на мой взгляд должен быть более простой способ преобразования CLOB в XMLType:

Код

CREATE OR REPLACE Procedure hrp_UpdateBatchValuePri(
  xmlUpd IN  CLOB,
  xmlNew OUT CLOB,
  RowCount OUT INTEGER,
  ReturnCode OUT INTEGER
) as

  domBatch dbms_xmldom.DOMDocument;
  nlBatch dbms_xmldom.DOMNodelist;
  ndBatch dbms_xmldom.DOMNode;
  elBatch dbms_xmldom.DOMElement;

  vaction number;
  id number;
  prg_npar number;
  psp_npos number;
  val varchar2(120);
  display_value varchar2(120);
  pri_nomer number;
  xmlTemp clob;

BEGIN

  ReturnCode := 0;
  RowCount := 0;
  
 --Следующие 3 строки были созданы из-за возникновения ошибки,
  --которая возникает при передаче CLOB'а напрямую в DOMDocument,
  --если длина CLOB'а больше 32K.
  
  if (LENGTHB(xmlUpd) >= 32768) then
    insert into tmp_clob(data) values (xmlUpd);
    select data into xmlTemp from tmp_clob;
    DELETE FROM tmp_clob;
    
    domBatch:=dbms_xmldom.newDOMDocument(XMLType(xmlTemp));
  else
    domBatch:=dbms_xmldom.newDOMDocument(XMLType(To_CHAR(xmlUpd)));
  end if;

     nlBatch:=dbms_xmldom.getChildNodes(dbms_xmldom.item(dbms_xmldom.getElementsByTagName(domBatch, 'ValuePri') ,0));
     for Itm in 1..dbms_xmldom.getLength(nlBatch) loop

         ndBatch:=dbms_xmldom.item(nlBatch,Itm-1);
         elBatch := dbms_xmldom.makeElement(ndBatch);
         vaction:=dbms_xmldom.getAttribute(elBatch,'action');

         if vaction=1 then
--******************Добавление**************************************

             prg_npar:=dbms_xmldom.getAttribute(elBatch,'prg_npar');
             psp_npos:=dbms_xmldom.getAttribute(elBatch,'psp_npos');
             val:=dbms_xmldom.getAttribute(elBatch,'value');
             display_value:=dbms_xmldom.getAttribute(elBatch,'display_value');
             pri_nomer:=dbms_xmldom.getAttribute(elBatch,'pri_nomer');
             
             INSERT INTO VALUEPRI (ID, PRG_NPAR, PSP_NPOS, VALUE, DISPLAYVALUE, PRI_NOMER) VALUES
             (VALUEPRI_ID_SEQ.NEXTVAL, prg_npar, psp_npos, val, display_value, pri_nomer);
             
             SELECT VALUEPRI_ID_SEQ.CURRVAL INTO id FROM DUAL;
             
             dbms_xmldom.setAttribute(elBatch,'id', id);
             RowCount := RowCount + SQL%ROWCOUNT;
         elsif vaction=2 then
--******************Модификация**************************************
             id := dbms_xmldom.getAttribute(elBatch,'id');
             prg_npar:=dbms_xmldom.getAttribute(elBatch,'prg_npar');
             psp_npos:=dbms_xmldom.getAttribute(elBatch,'psp_npos');
             val:=dbms_xmldom.getAttribute(elBatch,'value');
             display_value:=dbms_xmldom.getAttribute(elBatch,'display_value');
             pri_nomer:=dbms_xmldom.getAttribute(elBatch,'pri_nomer');
             
             UPDATE VALUEPRI v SET
                    v.PRG_NPAR = prg_npar, v.PSP_NPOS = psp_npos,
                    v.VALUE = val, v.DISPLAYVALUE = display_value,
                    v.PRI_NOMER = pri_nomer
                    WHERE v.ID = id;

             RowCount := RowCount + SQL%ROWCOUNT;
         end if;
     end loop;
     
     dbms_xmldom.writeToClob(domBatch,xmlNew);
     EXCEPTION WHEN OTHERS THEN ReturnCode := sqlcode;
END;

Автор: smolbars 23.10.2005, 13:26
А как победить подобную же проблему если использовать не dom а xsu и надо перегонять xml в файл
а то у меня строки километровые
http://forum.vingrad.ru/index.php?showtopic=67235
там описано в чем проблема
В принципе (и без принципа тоже) это та же проблема что и у VIAcom
Но что то по кускам у меня не получается - может за это время VIAcom нашел решение
Я конечно написал альтернативный вариант на delphi но с клиентского мется меня как-то не плющит такое делать - просто время поджимало
Может кто подскажет как обойти это ограничение 32767
smile

Автор: Кану 2.11.2005, 08:39
Как вариант такой обход:

Код


ttt clob := null;
begin

DBMS_LOB.createtemporary(ttt,true);
DBMS_LOB.open(ttt,1);
DBMS_LOB.append(ttt,aaa));

end;


где ttt - понятно что, а
ааа - clob храняший наши данные, но не желающий вернуть их целиком. "ааа" создавался так же, как и ttt с помощью createtemporary.
Я интереса ради передал там 8 метров. В принципе все это дело работает, но вопрос - насколько нужен такой объем инфы... Для получения данных всетаки, больше подойдет считывание по кускам, если нет желания заставить комп подавиться обилием инфы.

Пробуйте.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)