Generar CSV desde Oracle DB
En alguna ocasion he tenido que generar ficheros CSV desde Oracle.
El siguiente procedimiento recibe una query, un carecter que servirá de separador del fichero CSV ( por defecto una coma ), y
el nombre del fichero que vamos a generar.
PROCEDURE generar_fichero_csv( p_query VARCHAR2, p_separador VARCHAR2 DEFAULT ',', p_nombre_fichero VARCHAR2 )IS v_lineas number; BEGIN --create directory dir_informes as '/tmp/informes'; 'DIR_INFORMES' v_lineas := dump_csv( p_query => p_query, p_separator => p_separador, p_dir => 'DIR_INFORMES', p_filename => p_nombre_fichero); dbms_output.put_line('Lneas generadas: ' || v_lineas); END generar_fichero_csv;
Un ejemplo de uso seria el siguiente:
generar_fichero_csv( p_query => 'SELECT * from TABLA', p_separador => ';', p_nombre_fichero => 'informe_altas.csv');
El quiz de la cuestión reside en la función dump_csv que es la que realmente genera el fichero csv,
ya que la llamada anterior es simplemente un wrapper:
FUNCTION dump_csv( p_query IN VARCHAR2, p_separator IN VARCHAR2 DEFAULT ',', p_dir IN VARCHAR2 , p_filename IN VARCHAR2 ) RETURN NUMBER IS l_output utl_file.file_type; l_theCursor INTEGER DEFAULT dbms_sql.open_cursor; l_columnValue VARCHAR2(2000); l_status INTEGER; l_colCnt NUMBER DEFAULT 0; l_separator VARCHAR2(10) DEFAULT ''; l_cnt NUMBER DEFAULT 0; l_desc_tab dbms_sql.desc_tab; l_cols number; BEGIN l_output := utl_file.fopen( p_dir, p_filename, 'w' ); l_theCursor := dbms_sql.open_cursor; dbms_sql.parse( l_theCursor, p_query, dbms_sql.native ); dbms_sql.describe_columns( l_theCursor, l_cols, l_desc_tab ); -- nombre columnas l_separator := ''; --escribir el nombre de las columnas FOR i IN 1 .. l_cols LOOP utl_file.put( l_output, l_separator || l_desc_tab(i).col_name ); l_separator := p_separator; END LOOP; utl_file.new_line( l_output ); FOR I IN 1 .. 255 LOOP BEGIN dbms_sql.define_column( l_theCursor, i, l_columnValue, 2000 ); l_colCnt := i; EXCEPTION WHEN OTHERS THEN IF ( SQLCODE = -1007 ) THEN EXIT; ELSE RAISE; END IF; END; END LOOP; dbms_sql.define_column( l_theCursor, 1, l_columnValue, 2000 ); l_status := dbms_sql.execute(l_theCursor); IF l_status = 0 THEN NULL; END IF; LOOP EXIT WHEN ( dbms_sql.fetch_rows(l_theCursor) <= 0 ); l_separator := ''; FOR I IN 1 .. l_colCnt LOOP dbms_sql.column_value( l_theCursor, i, l_columnValue ); utl_file.put( l_output, l_separator || l_columnValue ); l_separator := p_separator; END LOOP; utl_file.new_line( l_output ); l_cnt := l_cnt+1; END LOOP; dbms_sql.close_cursor(l_theCursor); utl_file.fclose( l_output ); RETURN l_cnt; END dump_csv;
Espero que a alguien le sea de utilidad.