I want to extract some queries to a CSV output format. Unfortunately, I can\'t use any fancy SQL client or any language to do it. I must use SQLPLUS.
How do I do it?
I wrote this purely SQLPlus script to dump tables to CSV in 1994.
As noted in the script comments, someone at Oracle put my script in an Oracle Support note, but without attribution.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
The script also also builds a control file and a parameter file for SQL*LOADER
I use this command for scripts which extracts data for dimensional tables (DW). So, I use the following syntax:
set colsep '|'
set echo off
set feedback off
set linesize 1000
set pagesize 0
set sqlprompt ''
set trimspool on
set headsep off
spool output.dat
select '|', <table>.*, '|'
from <table>
where <conditions>
spool off
And works. I don't use sed for format the output file.
It's crude, but:
set pagesize 0 linesize 500 trimspool on feedback off echo off
select '"' || empno || '","' || ename || '","' || deptno || '"' as text
from emp
spool emp.csv
/
spool off
You should be aware that values of fields could contain commas and quotation characters, so some of the suggested answers would not work, as the CSV output file would not be correct. To replace quotation characters in a field, and replace it with the double quotation character, you can use the REPLACE function that oracle provides, to change a single quote to double quote.
set echo off
set heading off
set feedback off
set linesize 1024 -- or some other value, big enough
set pagesize 50000
set verify off
set trimspool on
spool output.csv
select trim(
'"' || replace(col1, '"', '""') ||
'","' || replace(col2, '"', '""') ||
'","' || replace(coln, '"', '""') || '"' ) -- etc. for all the columns
from yourtable
/
spool off
Or, if you want the single quote character for the fields:
set echo off
set heading off
set feedback off
set linesize 1024 -- or some other value, big enough
set pagesize 50000
set verify off
set trimspool on
spool output.csv
select trim(
'"' || replace(col1, '''', '''''') ||
'","' || replace(col2, '''', '''''') ||
'","' || replace(coln, '''', '''''') || '"' ) -- etc. for all the columns
from yourtable
/
spool off
prefer to use "set colsep" in sqlplus prompt instead of editing col name one by one. Use sed to edit the output file.
set colsep '","' -- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
With newer versions of client tools, there are multiple options to format the query output. The rest is to spool it to a file or save the output as a file depending on the client tool. Here are few of the ways:
Using the SQL*Plus commands you could format to get your desired output. Use SPOOL to spool the output to a file.
For example,
SQL> SET colsep ,
SQL> SET pagesize 20
SQL> SET trimspool ON
SQL> SET linesize 200
SQL> SELECT * FROM scott.emp;
EMPNO,ENAME ,JOB , MGR,HIREDATE , SAL, COMM, DEPTNO
----------,----------,---------,----------,---------,----------,----------,----------
7369,SMITH ,CLERK , 7902,17-DEC-80, 800, , 20
7499,ALLEN ,SALESMAN , 7698,20-FEB-81, 1600, 300, 30
7521,WARD ,SALESMAN , 7698,22-FEB-81, 1250, 500, 30
7566,JONES ,MANAGER , 7839,02-APR-81, 2975, , 20
7654,MARTIN ,SALESMAN , 7698,28-SEP-81, 1250, 1400, 30
7698,BLAKE ,MANAGER , 7839,01-MAY-81, 2850, , 30
7782,CLARK ,MANAGER , 7839,09-JUN-81, 2450, , 10
7788,SCOTT ,ANALYST , 7566,09-DEC-82, 3000, , 20
7839,KING ,PRESIDENT, ,17-NOV-81, 5000, , 10
7844,TURNER ,SALESMAN , 7698,08-SEP-81, 1500, , 30
7876,ADAMS ,CLERK , 7788,12-JAN-83, 1100, , 20
7900,JAMES ,CLERK , 7698,03-DEC-81, 950, , 30
7902,FORD ,ANALYST , 7566,03-DEC-81, 3000, , 20
7934,MILLER ,CLERK , 7782,23-JAN-82, 1300, , 10
14 rows selected.
SQL>
Alternatively, you could use the new /*csv*/
hint in SQL Developer.
/*csv*/
For example, in my SQL Developer Version 3.2.20.10:
Now you could save the output into a file.
New in SQL Developer version 4.1, use the following just like sqlplus command and run as script. No need of the hint in the query.
SET SQLFORMAT csv
Now you could save the output into a file.