How do I spool to a CSV formatted file using SQLPLUS?

后端 未结 16 942
执笔经年
执笔经年 2020-11-22 15:40

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?

相关标签:
16条回答
  • 2020-11-22 16:39

    You could also use the following, although it does introduce spaces between fields.

    set colsep ,     -- separate columns with a comma
    set pagesize 0   -- No header rows
    set trimspool on -- remove trailing blanks
    set headsep off  -- this may or may not be useful...depends on your headings.
    set linesize X   -- X should be the sum of the column widths
    set numw X       -- X should be the length you want for numbers (avoid scientific notation on IDs)
    
    spool myfile.csv
    
    select table_name, tablespace_name 
      from all_tables
     where owner = 'SYS'
       and tablespace_name is not null;
    

    Output will be like:

        TABLE_PRIVILEGE_MAP           ,SYSTEM                        
        SYSTEM_PRIVILEGE_MAP          ,SYSTEM                        
        STMT_AUDIT_OPTION_MAP         ,SYSTEM                        
        DUAL                          ,SYSTEM 
    ...
    

    This would be a lot less tedious than typing out all of the fields and concatenating them with the commas. You could follow up with a simple sed script to remove whitespace that appears before a comma, if you wanted.

    Something like this might work...(my sed skills are very rusty, so this will likely need work)

    sed 's/\s+,/,/' myfile.csv 
    
    0 讨论(0)
  • 2020-11-22 16:43

    There is a problem using sqlplus to create csv files. If you want the column headers only once in the output and there are thousands or millions of rows, you cannot set pagesize large enough not to get a repeat. The solution is to start with pagesize = 50 and parse out the headers, then issue the select again with pagesize = 0 to get the data. See bash script below:

    #!/bin/bash
    FOLDER="csvdata_mydb"
    CONN="192.168.100.11:1521/mydb0023.world"
    CNT=0376
    ORD="0376"
    TABLE="MY_ATTACHMENTS"
    
    sqlplus -L logn/pswd@//${CONN}<<EOF >/dev/null
    set pagesize 50;
    set verify off;
    set feedback off;
    set long 99999;
    set linesize 32767;
    set trimspool on;
    col object_ddl format A32000;
    set colsep ,;
    set underline off;
    set headsep off;
    spool ${ORD}${TABLE}.tmp;
    select * from tblspc.${TABLE} where rownum < 2;
    EOF
    LINES=`wc -l ${ORD}${TABLE}.tmp | cut -f1 -d" "`
    [ ${LINES} -le 3 ] && {
      echo "No Data Found in ${TABLE}."
    }
    [ ${LINES} -gt 3 ] && {
      cat ${ORD}${TABLE}.tmp | sed -e 's/ * / /g' -e 's/^ //' -e 's/ ,/,/g' -e 's/, /,/g' | tail -n +3 | head -n 1 > ./${ORD}${TABLE}.headers
    }
    
    sqlplus -L logn/pswd@//${CONN}<<EOF >/dev/null
    set pagesize 0;
    set verify off;
    set feedback off;
    set long 99999;
    set linesize 32767;
    set trimspool on;
    col object_ddl format A32000;
    set colsep ,;
    set underline off;
    set headsep off;
    spool ${ORD}${TABLE}.tmp;
    select * from tblspc.${TABLE};
    EOF
    LINES=`wc -l ${ORD}${TABLE}.tmp | cut -f1 -d" "`
    [ ${LINES} -le 3 ] && {
      echo "No Data Found in ${TABLE}."
    }
    [ ${LINES} -gt 3 ] && {
      cat ${ORD}${TABLE}.headers > ${FOLDER}/${ORD}${TABLE}.csv
      cat ${ORD}${TABLE}.tmp | sed -e 's/ * / /g' -e 's/^ //' -e 's/ ,/,/g' -e 's/, /,/g' | tail -n +2 | head -n -1 >> ${FOLDER}/${ORD}${TABLE}.csv
    }
    
    0 讨论(0)
  • 2020-11-22 16:44

    If you are using 12.2, you can simply say

    set markup csv on
    spool myfile.csv
    
    0 讨论(0)
  • 2020-11-22 16:44

    Use vi or vim to write the sql, use colsep with a control-A (in vi and vim precede the ctrl-A with a ctrl-v). Be sure to set the linesize and pagesize to something rational and turn on trimspool and trimout.

    spool it off to a file. Then...

    sed -e 's/,/;/g' -e 's/ *{ctrl-a} */,/g'  {spooled file}  > output.csv
    

    That sed thing can be turned into a script. The " *" before and after the ctrl-A squeezes out all the useless spaces. Isn't it great that they bothered to enable html output from sqlplus but NOT native csv?????

    I do it this way because it handles commas in the data. I turns them to semi-colons.

    0 讨论(0)
提交回复
热议问题