Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Edgar.

Asked: March 23, 2018 - 2:55 pm UTC

Last updated: March 27, 2018 - 5:32 am UTC

Version: 12c

Viewed 1000+ times

You Asked

Hi, Tom.
Estoy diseñando un pequeño pkg para encapsular el codigo de generación de archivos .csv de interfaces de aplicación, pero cuando se trata de un set de datos muy grande la escritura del archivo falla, dando un error ORA-29285

Mi pregunta como puedo controlar esa falla y manejar el tamaño de la linea que trato de escribir sin afectar el rendimiento del pkg.

procedure clobTofile (p_clob clob, p_directory varchar2 := 'DIR_CSV',
                       p_filename varchar2 := 'file'||userenv('SESSIONID')||to_char(systimestamp,'ddmmyyyyhh24miss')||'.csv')
  IS
    t_clob clob := p_clob;
    t_fh utl_file.file_type;
    amount pls_integer := 32767;
    offset integer := 1;
    l_leng    pls_integer := 32700;
    l_fileleng number := dbms_lob.getlength(p_clob);
    lc_buffer varchar2(32767);
    lberr_29285 exception;
    pragma EXCEPTION_INIT (lberr_29285, -29285);
  begin
    t_fh := utl_file.fopen( p_directory, p_filename, 'w');
    begin
      if ( dbms_lob.isopen(t_clob) != 1 )
      then
        dbms_lob.open(t_clob, 0);
      end if;
      --
/*
  intente controlar el maximo del campo char logre romper en segmentos tomando el string 32700 como maximo,
  sin embargo cuando recibo una linea o segmento que llega a medir 3213b pero no la longitud maxima controlada
  falla la escritura.
*/
      case when l_fileleng >= l_leng
           then
           --
           loop
               amount := instr(dbms_lob.substr( t_clob, l_leng, offset), l_endofline, -1);
               exit when nvl(amount,0) = 0;
               lc_buffer := dbms_lob.substr( t_clob, amount, offset);
               utl_file.put_line( t_fh, lc_buffer);
               offset := offset + amount;
           end loop;
      else
        utl_file.put_line( t_fh, dbms_lob.substr( t_clob, l_fileleng, offset));        
      end case;
      if ( dbms_lob.isopen(t_clob) = 1 ) then
           dbms_lob.close(t_clob);
      end if;
    exception
      when lberr_29285 then
        dbms_output.put_line('Error :Error de escritura en el archivo archivo destino');
      raise;
      when others then
         dbms_output.put_line('Error : '||sqlerrm);
         raise;
    end printout;
    utl_file.fclose( t_fh );
  end;


with LiveSQL Test Case:

and Connor said...

I hope I understand your question - I used google translate.

By default, UTL_FILE only allows a small line width.

Change

utl_file.fopen( p_directory, p_filename, 'w');

to

utl_file.fopen( p_directory, p_filename, 'w', 32767);

to allow a line to go up to 32k in size.

Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Why reinvent the wheel?

Andrew Sayer, March 25, 2018 - 1:19 pm UTC

There's already an inbuilt procedure for this: clob2file

If you're on below 12.2 then it lives in dbms_xslProcessor, 12.2 and above it has been moved to its more natural home in dbms_lob https://docs.oracle.com/en/database/oracle/oracle-database/12.2/arpls/DBMS_LOB.html#GUID-006129FC-1335-4B9F-9D9A-40130F6D6F45
Connor McDonald
March 27, 2018 - 5:32 am UTC

good input

Gracias

Edgar Corona, March 26, 2018 - 3:34 pm UTC

Connor, Buen Dia. excelente ese parametro al Utl_file resolvio el problema.

Mil gracias.


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library