CREATE OR REPLACE FUNCTION dump_csv_to_file
(
p_query IN VARCHAR2,
p_separator IN VARCHAR2 DEFAULT ';',
p_dir IN VARCHAR2,
p_filename IN VARCHAR2,
p_header IN VARCHAR2 DEFAULT 'Y',
p_limit IN INTEGER DEFAULT 100
) RETURN NUMBER IS
TYPE csv_cur_type IS REF CURSOR;
csv_cur csv_cur_type;
TYPE myarray IS TABLE OF VARCHAR2(4000);
l_data myarray;
l_query VARCHAR2(4000);
l_column_string VARCHAR2(2000);
l_thecursor INTEGER DEFAULT dbms_sql.open_cursor;
l_columnvalue VARCHAR2(2000);
l_status INTEGER;
l_colcnt NUMBER DEFAULT 0;
l_separator_csv VARCHAR2(10);
l_cnt NUMBER DEFAULT 0;
rec_tab dbms_sql.desc_tab;
l_output utl_file.file_type;
l_buffer VARCHAR2(32767) := NULL;
l_new_line VARCHAR2(10) := chr(10);
BEGIN
l_output := utl_file.fopen(p_dir, p_filename, 'w');
dbms_sql.parse(l_thecursor, p_query, dbms_sql.native);
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);
dbms_sql.describe_columns(l_thecursor, l_colcnt, rec_tab);
l_separator_csv := '';
FOR x IN 1 .. l_colcnt LOOP
l_column_string := l_column_string || l_separator_csv || rec_tab(x)
.col_name;
l_separator_csv := '||''' || p_separator || '''||';
END LOOP;
IF nvl(p_header, 'Y') != 'N' THEN
utl_file.put_line(l_output, l_column_string);
l_cnt := l_cnt + 1;
END IF;
l_query := regexp_replace(upper(p_query),
'^SELECT (.*?) FROM',
'SELECT ' || l_column_string || ' FROM');
OPEN csv_cur FOR l_query;
LOOP
FETCH csv_cur BULK COLLECT
INTO l_data LIMIT p_limit;
FOR j IN 1 .. l_data.count LOOP
IF length(l_buffer || l_data(j)) >= 30000 THEN
utl_file.put_line(l_output, l_buffer);
l_buffer := l_data(j);
ELSE
IF l_buffer IS NULL THEN
l_buffer := l_data(j);
ELSE
l_buffer := l_buffer || l_new_line || l_data(j);
END IF;
END IF;
l_cnt := l_cnt + 1;
END LOOP;
EXIT WHEN csv_cur%NOTFOUND;
END LOOP;
CLOSE csv_cur;
utl_file.put_line(l_output, l_buffer);
utl_file.fclose(l_output);
RETURN l_cnt;
EXCEPTION
WHEN OTHERS THEN
IF csv_cur%ISOPEN THEN
CLOSE csv_cur;
RAISE;
END IF;
END dump_csv_to_file;
CREATE OR REPLACE FUNCTION dump_csv_to_file
(
p_query IN VARCHAR2,
p_separator IN VARCHAR2 DEFAULT ';',
p_dir IN VARCHAR2,
p_filename IN VARCHAR2,
p_header IN VARCHAR2 DEFAULT 'Y',
p_limit IN INTEGER DEFAULT 100
) RETURN NUMBER IS
TYPE csv_cur_type IS REF CURSOR;
csv_cur csv_cur_type;
TYPE myarray IS TABLE OF VARCHAR2(4000);
l_data myarray;
l_query VARCHAR2(4000);
l_column_string VARCHAR2(2000);
l_thecursor INTEGER DEFAULT dbms_sql.open_cursor;
l_columnvalue VARCHAR2(2000);
l_status INTEGER;
l_colcnt NUMBER DEFAULT 0;
l_separator_csv VARCHAR2(10);
l_cnt NUMBER DEFAULT 0;
rec_tab dbms_sql.desc_tab;
l_output utl_file.file_type;
l_buffer VARCHAR2(32767) := NULL;
l_new_line VARCHAR2(10) := chr(10);
BEGIN
l_output := utl_file.fopen(p_dir, p_filename, 'w');
dbms_sql.parse(l_thecursor, p_query, dbms_sql.native);
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);
dbms_sql.describe_columns(l_thecursor, l_colcnt, rec_tab);
l_separator_csv := '';
FOR x IN 1 .. l_colcnt LOOP
l_column_string := l_column_string || l_separator_csv || rec_tab(x)
.col_name;
l_separator_csv := '||''' || p_separator || '''||';
END LOOP;
IF nvl(p_header, 'Y') != 'N' THEN
utl_file.put_line(l_output, l_column_string);
l_cnt := l_cnt + 1;
END IF;
l_query := regexp_replace(upper(p_query),
'^SELECT (.*?) FROM',
'SELECT ' || l_column_string || ' FROM');
OPEN csv_cur FOR l_query;
LOOP
FETCH csv_cur BULK COLLECT
INTO l_data LIMIT p_limit;
FOR j IN 1 .. l_data.count LOOP
IF length(l_buffer || l_data(j)) >= 30000 THEN
utl_file.put_line(l_output, l_buffer);
l_buffer := l_data(j);
ELSE
IF l_buffer IS NULL THEN
l_buffer := l_data(j);
ELSE
l_buffer := l_buffer || l_new_line || l_data(j);
END IF;
END IF;
l_cnt := l_cnt + 1;
END LOOP;
EXIT WHEN csv_cur%NOTFOUND;
END LOOP;
CLOSE csv_cur;
utl_file.put_line(l_output, l_buffer);
utl_file.fclose(l_output);
RETURN l_cnt;
EXCEPTION
WHEN OTHERS THEN
IF csv_cur%ISOPEN THEN
CLOSE csv_cur;
RAISE;
END IF;
END dump_csv_to_file;