Come si esegue lo spooling in un file in formato CSV utilizzando SQLPLUS?


143

Voglio estrarre alcune query in un formato di output CSV. Sfortunatamente, non posso usare nessun client SQL di fantasia o linguaggio per farlo. Devo usare SQLPLUS.

Come lo faccio?


Contrassegna come corretta la risposta fornita da @BobC. Manca il comando spool per stampare il file ma è la soluzione più semplice per esportare i dati in formato CSV.
rlar

Risposte:


28

Se stai usando 12.2, puoi semplicemente dire

set markup csv on
spool myfile.csv

Qualcuno sa come disattivare l'eco, l'ovvio "set echo off" non sembra funzionare con questo?
Quaternion

Supponendo che ciò avvenga poiché si sta eseguendo uno script e si scrive su un file, è sufficiente "disattivare termout"
BobC,

155

È inoltre possibile utilizzare quanto segue, sebbene introduca spazi tra i campi.

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;

L'output sarà come:

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

Questo sarebbe molto meno noioso che scrivere tutti i campi e concatenarli con le virgole. Puoi seguire un semplice script sed per rimuovere gli spazi bianchi che appaiono prima di una virgola, se lo desideri.

Qualcosa del genere potrebbe funzionare ... (le mie abilità sed sono molto arrugginite, quindi probabilmente avrà bisogno di lavoro)

sed 's/\s+,/,/' myfile.csv 

Il "," manca nella riga di testo. Anche l'headep off e la dimensione della linea X sono probabilmente utili. Modifica la risposta e la accetterò.
Daniel C. Sobral,

5
Il comando sed è: cat myfile.csv | sed -e 's / [\ t] * | / | / g; s / | [] * / | / g '> myfile.csv. Comunque, Oracle fa davvero schifo.
Stan,

2
E per ottenere un colpo di testa con i nomi delle colonne utilizzare set pagesize 1000al posto di 0. Nel mio commento precedente, non è possibile reindirizzare allo stesso file: cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv.
Stan,

1
Ho filtrato gli spazi vuoti e i trattini usati per sottolineare grepe in trquesto modo grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013,

1
@slayernoah il comando spool può prendere un percorso di directory e un nome file, in modo da poter specificare esattamente dove verrà posizionato il file di output. Altrimenti, dipende dalla posizione in cui si sta eseguendo lo script.
Gabe,

35

Uso questo comando per gli script che estrae i dati per le tabelle dimensionali (DW). Quindi, utilizzo la sintassi seguente:

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

E funziona. Non uso sed per formattare il file di output.


24

Vedo un problema simile ...

Devo eseguire lo spooling del file CSV da SQLPLUS, ma l'output ha 250 colonne.

Cosa ho fatto per evitare la fastidiosa formattazione dell'output di SQLPLUS:

set linesize 9999
set pagesize 50000
spool myfile.csv
select x
from
(
select col1||';'||col2||';'||col3||';'||col4||';'||col5||';'||col6||';'||col7||';'||col8||';'||col9||';'||col10||';'||col11||';'||col12||';'||col13||';'||col14||';'||col15||';'||col16||';'||col17||';'||col18||';'||col19||';'||col20||';'||col21||';'||col22||';'||col23||';'||col24||';'||col25||';'||col26||';'||col27||';'||col28||';'||col29||';'||col30 as x
from (  
      ...  here is the "core" select
     )
);
spool off

il problema è che perderai i nomi delle intestazioni di colonna ...

puoi aggiungere questo:

set heading off
spool myfile.csv
select col1_name||';'||col2_name||';'||col3_name||';'||col4_name||';'||col5_name||';'||col6_name||';'||col7_name||';'||col8_name||';'||col9_name||';'||col10_name||';'||col11_name||';'||col12_name||';'||col13_name||';'||col14_name||';'||col15_name||';'||col16_name||';'||col17_name||';'||col18_name||';'||col19_name||';'||col20_name||';'||col21_name||';'||col22_name||';'||col23_name||';'||col24_name||';'||col25_name||';'||col26_name||';'||col27_name||';'||col28_name||';'||col29_name||';'||col30_name from dual;

select x
from
(
select col1||';'||col2||';'||col3||';'||col4||';'||col5||';'||col6||';'||col7||';'||col8||';'||col9||';'||col10||';'||col11||';'||col12||';'||col13||';'||col14||';'||col15||';'||col16||';'||col17||';'||col18||';'||col19||';'||col20||';'||col21||';'||col22||';'||col23||';'||col24||';'||col25||';'||col26||';'||col27||';'||col28||';'||col29||';'||col30 as x
from (  
      ...  here is the "core" select
     )
);
spool off

So che è un po 'hardcore, ma funziona per me ...


abbiamo bisogno anche ||per le subquery ?, non credo sia necessario per le subquery. ma sì, è necessario per la selezione primaria.
davidb,

A cosa serve l'esterno extra select x? Questo dovrebbe funzionare senza di essa. @davidb, hai ragione sul fatto che la concatenazione non è richiesta nella subquery interna primaria, ma aliasing tutte le colonne come col1, col2 ... ecc. è richiesto lì.
Amit Naidu,

18

Con le versioni più recenti degli strumenti client, sono disponibili più opzioni per formattare l'output della query. Il resto è di eseguire lo spooling in un file o salvare l'output come file in base allo strumento client. Ecco alcuni dei modi:

  • SQL * Plus

Utilizzando i comandi SQL * Plus è possibile formattare per ottenere l'output desiderato. Utilizzare SPOOL per eseguire lo spooling dell'output in un file.

Per esempio,

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>
  • Versione per sviluppatori SQL pre 4.1

In alternativa, è possibile utilizzare il nuovo suggerimento in SQL Developer ./*csv*/

/*csv*/

Ad esempio, nella mia versione per sviluppatori SQL 3.2.20.10 :

inserisci qui la descrizione dell'immagine

Ora puoi salvare l'output in un file.

  • SQL Developer Versione 4.1

Novità di SQL Developer versione 4.1, utilizzare quanto segue proprio come il comando sqlplus ed eseguire come script. Non è necessario il suggerimento nella query.

SET SQLFORMAT csv

Ora puoi salvare l'output in un file.


12

So che questo è un vecchio thread, tuttavia ho notato che nessuno ha menzionato l'opzione di sottolineatura, che può rimuovere le sottolineature sotto le intestazioni di colonna.

set pagesize 50000--50k is the max as of 12c
set linesize 10000   
set trimspool on  --remove trailing blankspaces
set underline off --remove the dashes/underlines under the col headers
set colsep ~

select * from DW_TMC_PROJECT_VW;

Bella cattura dell'opzione di sottolineatura, necessaria quella.
knockando il

È bello se vuoi un CSV con una riga in alto che contiene il titolo / titoli per ogni colonna. Sarebbe di aiuto a chiunque desideri visualizzare il file CSV e capire cosa stanno guardando, ecc ...
Doc

10

È rozzo, ma:

set pagesize 0 linesize 500 trimspool on feedback off echo off

select '"' || empno || '","' || ename || '","' || deptno || '"' as text
from emp

spool emp.csv
/
spool off

7

È possibile formattare in modo esplicito la query per produrre una stringa delimitata con qualcosa lungo le linee di:

select '"'||foo||'","'||bar||'"'
  from tab

E imposta le opzioni di output come appropriato. Come opzione, la variabile COLSEP su SQLPlus consente di produrre file delimitati senza dover generare esplicitamente una stringa con i campi concatenati insieme. Tuttavia, dovrai inserire le virgolette attorno alle stringhe su tutte le colonne che potrebbero contenere caratteri virgola incorporati.


4

preferisco usare "set colsep" nel prompt sqlplus invece di modificare il nome col uno per uno. Usa sed per modificare il file di output.

set colsep '","'     -- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv


2

È necessario tenere presente che i valori dei campi potrebbero contenere virgole e caratteri di citazione, quindi alcune delle risposte suggerite non funzionerebbero, poiché il file di output CSV non sarebbe corretto. Per sostituire i caratteri di virgoletta in un campo e sostituirlo con il carattere di virgoletta doppia, è possibile utilizzare la funzione SOSTITUISCI fornita da Oracle, per modificare una virgoletta singola in virgoletta doppia.

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

Oppure, se si desidera il carattere di virgoletta singola per i campi:

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

Non trim()è necessario.
Amit Naidu,

1

Usa vi o vim per scrivere sql, usa colsep con un controllo-A (in vi e vim precedono il ctrl-A con un ctrl-v). Assicurati di impostare le dimensioni delle linee e delle pagine su qualcosa di razionale e attivare trimspool e trimout.

esegui lo spooling su un file. Poi...

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

Quella cosa sed può essere trasformata in una sceneggiatura. Il "*" prima e dopo il ctrl-A schiaccia tutti gli spazi inutili. Non è fantastico che si siano preoccupati di abilitare l'output html da sqlplus ma NON da CSV nativo ?????

Lo faccio in questo modo perché gestisce le virgole nei dati. Li trasformo in punto e virgola.


3
Questo fallisce il test "Devo usare SQLPlus".
Daniel C. Sobral,

0

Si è verificato un problema durante l'utilizzo di sqlplus per creare file CSV. Se si desidera che le intestazioni di colonna vengano visualizzate una sola volta nell'output e vi siano migliaia o milioni di righe, non è possibile impostare dimensioni di pagina sufficientemente grandi da non ripetere. La soluzione è iniziare con pagesize = 50 e analizzare le intestazioni, quindi eseguire nuovamente la selezione con pagesize = 0 per ottenere i dati. Vedi lo script bash di seguito:

#!/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
}



-3

È possibile utilizzare il suggerimento CSV. Vedi il seguente esempio:

select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.