CftClub.ru
Клуб специалистов ЦФТ-Банк

Ошибка CLOB2FILE в случае превышения размера 64k

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Уроки ЦФТ-Банк для начинающих
Предыдущая тема :: Следующая тема  
Автор Сообщение
Матвеев Евгений
Профи


Вступление в Клуб: 31.01.2012
СообщениеВт Авг 23, 2016 13:18   Ошибка CLOB2FILE в случае превышения размера 64k Ответить с цитатой
Полезность: Нет оценки
Делаю экспорт в xml
выгружаю так

Код:

procedure SaveXmlFile(p_file_name varchar2(255), p_dir_name varchar2(255), p_xml &xml.DOMDocument)
is
   file_path varchar2(255) := replace([SYSTEM_PARAMS]::[GET]('PATH',null)||p_dir_name,'/',slash);
   f_clob CLOB;
begin
   dbms_lob.createtemporary(f_clob, false);
   &xml.writeToClob(p_xml, f_clob);-- выгрузка в CLOB
   clob2file(f_clob, file_path, p_file_name,'UTF8');
   dbms_lob.freetemporary(f_clob);   
end;


Если p_xml (а соответственно и f_clob) менее 64k, всё гуд, файлы формируются

Если более 64k, то



Цитата:

В настоящий момент операция невозможна:
PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения

ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 38

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 57

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 201

ORA-06512: на "IBS.Z$U$3158650867", line 75

ORA-06512: на line 1

BEGIN

$$$.Z$U$3158650867.P(?,?,?);

END;


Как быть?
OlegFB
Участник - экстремал


Вступление в Клуб: 11.07.2007
СообщениеВт Авг 23, 2016 15:27   Re: Ошибка CLOB2FILE в случае превышения размера 64k Ответить с цитатой
Полезность: 2
Матвеев Евгений пишет:
Делаю экспорт в xml
выгружаю так

Код:

procedure SaveXmlFile(p_file_name varchar2(255), p_dir_name varchar2(255), p_xml &xml.DOMDocument)
is
   file_path varchar2(255) := replace([SYSTEM_PARAMS]::[GET]('PATH',null)||p_dir_name,'/',slash);
   f_clob CLOB;
begin
   dbms_lob.createtemporary(f_clob, false);
   &xml.writeToClob(p_xml, f_clob);-- выгрузка в CLOB
   clob2file(f_clob, file_path, p_file_name,'UTF8');
   dbms_lob.freetemporary(f_clob);   
end;


Если p_xml (а соответственно и f_clob) менее 64k, всё гуд, файлы формируются

Если более 64k, то



Цитата:

В настоящий момент операция невозможна:
PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения

ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 38

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 57

ORA-06512: на "IBS.Z$FM_MESS_SET_RCI_SAVE_MESS", line 201

ORA-06512: на "IBS.Z$U$3158650867", line 75

ORA-06512: на line 1

BEGIN

$$$.Z$U$3158650867.P(?,?,?);

END;


Как быть?

Насколько я в курсе - никак не лечится.
Мы обходили костыликом: в цикле вычитывали данные блоками по сколько-то там Кб и писали в файл уже эти блоки частями.
Матвеев Евгений
Профи


Вступление в Клуб: 31.01.2012
СообщениеВт Авг 23, 2016 15:30    Ответить с цитатой
Полезность: Нет оценки
А есть пример костылика?

Костылика на запись...

и

Костылика на чтение...
OlegFB
Участник - экстремал


Вступление в Клуб: 11.07.2007
СообщениеВт Авг 23, 2016 15:40    Ответить с цитатой
Полезность: Нет оценки
Матвеев Евгений пишет:
А есть пример костылика?

Костылика на запись...

и

Костылика на чтение...


Под рукой нет - в другом банке было...

Пример алгоритма на PL/SQL тут http://www.sql.ru/forum/265307/clob-to-file-using-pl-sql
Матвеев Евгений
Профи


Вступление в Клуб: 31.01.2012
СообщениеВт Авг 23, 2016 22:26    Ответить с цитатой
Полезность: Нет оценки
Наверное как то так это должно выглядеть

Код:

procedure clob2file(p_file_path varchar2(2000),p_file_name varchar2(2048),cl clob) is
   file      integer;
   buffer      varchar2(32000);
   idx       integer:=1;
begin
   file := stdio.open(p_file_path, p_file_name,'w');

   buffer:=substr(cl,idx,32000);
    while length(buffer) != 0
    loop
       stdio.fput(file,buffer,true);
       idx:=idx+32000;
       buffer:=substr(cl,idx,32000);
    end loop;
    stdio.close(file);
end;



Костылик на запись кусочками по 32000 байт
Alkov
Профи


Вступление в Клуб: 23.09.2010
СообщениеСр Авг 24, 2016 02:29    Ответить с цитатой
Полезность: 1
у меня кодировка так не та сохранялась, конвертил в blob типа такого:
Код:

procedure write_to_file
         ( p_clob   in      clob
         , p_dir            varchar
         , p_fname         varchar
         )
is

v_blob   blob;
iFile      integer;
rwChunk   raw(32767);
iSize      integer  := 32765;   --   запланированный объем порции данных

lang_ctx   dbms_lob.default_lang_ctx%type := dbms_lob.default_lang_ctx;
dest_offs   integer :=1;
src_offs   integer :=1;
warn      integer;
utf8_sid   integer := 873;    -- AL32UTF8
win_sid   integer := 171;    -- CL8MSWIN1251
lenb      number;
cnt      integer;
begin
   dbms_lob.createtemporary(v_blob, true, dbms_lob.call);
   
   dbms_lob.convertToBlob(v_blob, p_clob, dbms_lob.lobmaxsize, dest_offs, src_offs, utf8_sid, lang_ctx, warn);
   
   iFile := stdio.open(p_dir, p_fname, 'w');       

   lenb := dbms_lob.getlength(v_blob);
   if lenb <> 0 then      
      cnt := ceil(lenb / iSize);
      for i in 1 .. cnt loop
         dbms_lob.read(v_blob , iSize, (i - 1) * iSize + 1, rwChunk);
         stdio.fwrite(iFile, rwChunk,  utl_raw.length(rwChunk) );
      end loop;
   end if;
   
   stdio.f_close(iFile);
end;
Матвеев Евгений
Профи


Вступление в Клуб: 31.01.2012
СообщениеСр Авг 24, 2016 02:33    Ответить с цитатой
Полезность: 1
Тоже сейчас столкнулся, минут 40 убил, в итоге решил вот так:

Код:



procedure clob2file(p_clob CLOB , p_filedir varchar2, p_filename varchar2, codePage varchar2 default null) is
file integer;
buf_size const integer := 32000;
amount integer := buf_size;
offset integer := 1;
buffer VARCHAR2(32000);
buffer_conv varchar2(32000);
buffer_row    raw(32000);
our_charset varchar2;
begin
   if codePage is not null then   
      select a(a.value) in NLS_DATABASE_PARAMETERS%rowtype where a.PARAMETER = 'NLS_CHARACTERSET' into our_charset;
   end if;
   file := stdio.f_open(p_filedir||slash||p_filename, 'w');
   &debug('p_filename=['||p_filedir||slash||p_filename||']',1);
   while amount = buf_size loop
      dbms_lob.read(p_clob, amount, offset, buffer);
      buffer_conv := convert(buffer, codePage, our_charset);
      buffer_row := utl_raw.cast_to_raw(buffer_conv);
      stdio.f_write(file, buffer_row);
      --stdio.write_str(file, , null, null, false);
      offset := offset + amount;
   end loop;
   stdio.f_close(file);
end;

...
clob2file(f_clob, file_path, p_file_name,'CL8MSWIN1251');
...


Подходит кодировка CL8MSWIN1251

Код:

<?xml version="1.0" encoding="ISO-8859-5"?>
<Main>
  <FmMessSet BANK_PRODUCT="CUSTOMER_SERVICE_9" WAY_SELL="CS9_CHDP">
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="SMS" COND="FM_MESSAGE" TEMPLATE="ЧДП Регистрация заявки SMS">
      <RECIP_CLIENTS PARTICIPANT_CODE="REQUESTER" PARTICIPANT_NAME="Инициатор запроса"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="MAIL" COND="FM_MESSAGE" TEMPLATE="ЧДП Регистрация заявки">
      <RECIP_OTHER NAME="sergey.panin-extern@bank.ru" CONTACT="sergey.panin-extern@bank.ru"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="MAIL" COND="CS_MAIL_ERROR_DATA" TEMPLATE="ЧДП\ПДП Отказ">
      <RECIP_OTHER NAME="sergey.panin-extern@bank.ru" CONTACT="sergey.panin-extern@bank.ru"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="SMS" COND="CS_MAIL_ERROR_DATA" TEMPLATE="ЧДП\ПДП Отказ SMS">
      <RECIP_CLIENTS PARTICIPANT_CODE="REQUESTER" PARTICIPANT_NAME="Инициатор запроса"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="SMS" COND="FM_MESSAGE" TEMPLATE="ПДП Регистрация заявки SMS">
      <RECIP_CLIENTS PARTICIPANT_CODE="REQUESTER" PARTICIPANT_NAME="Инициатор запроса"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="SMS" COND="FM_MESSAGE" TEMPLATE="ЧДП\ПДП Отказ SMS - кредитный договор закрыт">
      <RECIP_CLIENTS PARTICIPANT_CODE="REQUESTER" PARTICIPANT_NAME="Инициатор запроса"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="MAIL" COND="FM_MESSAGE" TEMPLATE="ПДП Регистрация заявки">
      <RECIP_OTHER NAME="sergey.panin-extern@bank.ru" CONTACT="sergey.panin-extern@bank.ru"/>
    </FmMessages>
    <FmMessages STATUS="CS_REPLY" TYPE_INFO="MAIL" COND="FM_MESSAGE" TEMPLATE="ЧДП\ПДП Отказ - кредитный договор закрыт">
      <RECIP_OTHER NAME="sergey.panin-extern@bank.ru" CONTACT="sergey.panin-extern@bank.ru"/>
    </FmMessages>
  </FmMessSet>
</Main>

Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Уроки ЦФТ-Банк для начинающих Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах