Question

In a number of places in my applications, I need to display data as CSV.

For this, I usually loop through a cursor and build the CSV.

for j in c_get_mydata loop
    v_CSV := v_CSV || ', ' || j.column_value;
end loop;

How can I write a re-usable function that could accept a query and return a CSV string? Do you recommend having this as a separate function or is it better to process each query like above? If you recommend having it as a separate function, do you recommend that the function take the string of the query or the resultant cursor as input?

EDIT:

Clarification: I want to display a single column of data as one row, separated by commas.

E.g.: Tom, Dick, Harry, Sally

I'm not looking to display multi-column data on multiple rows as:

Tom, 18, London
Dick, 22, New York
Harry, 16, San Fransisco
Sally, 18, Paris

EDIT 2:

I found out about the collect function:

select collect(employee_name)
from employees

This returns me a dataset, but how can I convert it into a string?

Was it helpful?

Solution

The simplest option would generally by to use the DBMS_SQL package. Tom Kyte has a good example with his dump_csv procedure. Of course, you probably want to write the results to a CLOB rather than writing it to a file using utl_file but that's a relatively easy tweak to make.

OTHER TIPS

Old question and already correctly answered I know, but as this is one of the top Google hits for "oracle cursor to csv" and I've just written something to do this, I thought I'd post a new answer.

From Oracle 11.2 onwards DBMS_SQL can handle a normal ref cursor rather than just a string as in Tom Kyte's 2000 solution. You ingest it into DBMS_SQL using

l_cursor_id := dbms_sql.to_cursor_number(your_refcursor);

(l_cursor_id will then contain a meaningless generated number that DBMS_SQL uses to track its corresponding internal values.)

Since the ref cursor was already opened and parsed, you skip those steps and call

dbms_sql.describe_columns(l_cursor_id, l_col_count, l_cursor_columns);

where l_cursor_columns (an OUT parameter that DBMS_SQL populates for you) is a dbms_sql.desc_tab, which is an array of column definitions populated with an entry for each column in the query and containing the column name, datatype etc, and l_col_count somewhat redundantly contains the same value as l_cursor_columns.count. You then need to loop through this array calling dbms_sql.define_column to tell DBMS_SQL to handle each one using the datatype it just told you, a rather verbose step I can never quite see the point of. (It does allow you to treat all '%CHAR%' types as varchar2 etc so I guess it allows some flexibility.)

Then it's just a matter of calling dbms_sql.fetch_rows in a loop and processing the results. I put this in a pipelined table function which accepts a ref cursor argument, so you get something like this:

select column_value
from   table(csv.report(cursor(
           select * from dept  -- << Use any query here
       )));

COLUMN_VALUE
----------------------------------------------
10,ACCOUNTING,NEW YORK
20,RESEARCH,DALLAS
30,SALES,CHICAGO
40,OPERATIONS,BOSTON

4 rows selected.

Full writeup and code here: www.williamrobertson.net/documents/refcursor-to-csv.shtml

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top