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?
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?
Risposte:
Se stai usando 12.2, puoi semplicemente dire
set markup csv on
spool myfile.csv
È 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
set pagesize 1000
al 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
.
grep
e in tr
questo modo grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.
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.
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 ...
||
per le subquery ?, non credo sia necessario per le subquery. ma sì, è necessario per la selezione primaria.
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ì.
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:
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>
In alternativa, è possibile utilizzare il nuovo suggerimento in SQL Developer ./*csv*/
/*csv*/
Ad esempio, nella mia versione per sviluppatori SQL 3.2.20.10 :
Ora puoi salvare l'output in un file.
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.
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;
È 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
È 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.
Una volta ho scritto un piccolo script SQL * Plus che utilizza dbms_sql
e dbms_output
per creare un CSV (in realtà un SSV). Puoi trovarlo sul mio repository githup .
È 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
trim()
è necessario.
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.
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
}
Ho scritto questo script puramente SQLPlus per scaricare tabelle in CSV nel 1994.
Come notato nei commenti sulla sceneggiatura, qualcuno di Oracle ha inserito la mia sceneggiatura in una nota del supporto Oracle, ma senza attribuzione.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
Lo script crea inoltre un file di controllo e un file di parametri per SQL * LOADER
spool D:\test.txt
select * from emp
spool off
È 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;