Ich möchte einige Abfragen in ein CSV-Ausgabeformat extrahieren. Leider kann ich dafür keinen ausgefallenen SQL-Client oder eine andere Sprache verwenden. Ich muss SQLPLUS verwenden.
Wie mache ich es?
Ich möchte einige Abfragen in ein CSV-Ausgabeformat extrahieren. Leider kann ich dafür keinen ausgefallenen SQL-Client oder eine andere Sprache verwenden. Ich muss SQLPLUS verwenden.
Wie mache ich es?
Antworten:
Wenn Sie 12.2 verwenden, können Sie einfach sagen
set markup csv on
spool myfile.csv
Sie können auch Folgendes verwenden, obwohl Leerzeichen zwischen Feldern eingefügt werden.
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;
Die Ausgabe lautet wie folgt:
TABLE_PRIVILEGE_MAP ,SYSTEM
SYSTEM_PRIVILEGE_MAP ,SYSTEM
STMT_AUDIT_OPTION_MAP ,SYSTEM
DUAL ,SYSTEM
...
Dies wäre viel weniger mühsam, als alle Felder auszutippen und mit Kommas zu verknüpfen. Wenn Sie möchten, können Sie ein einfaches sed-Skript verwenden, um Leerzeichen zu entfernen, die vor einem Komma angezeigt werden.
So etwas könnte funktionieren ... (meine Fähigkeiten sind sehr verrostet, daher wird dies wahrscheinlich Arbeit erfordern)
sed 's/\s+,/,/' myfile.csv
set pagesize 1000
anstelle von 0. In meinem vorherigen Kommentar können Sie nicht zur gleichen Datei umleiten : cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv
.
grep
und tr
wie diese grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.
Ich verwende diesen Befehl für Skripte, die Daten für Dimensionstabellen (DW) extrahieren. Daher verwende ich die folgende 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
Und funktioniert. Ich verwende sed nicht zum Formatieren der Ausgabedatei.
Ich sehe ein ähnliches Problem ...
Ich muss eine CSV-Datei aus SQLPLUS spoolen, aber die Ausgabe enthält 250 Spalten.
Was ich getan habe, um die lästige Formatierung der SQLPLUS-Ausgabe zu vermeiden:
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
Das Problem ist, dass Sie Spaltenüberschriften verlieren ...
Sie können dies hinzufügen:
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
Ich weiß, dass es ein bisschen Hardcore ist, aber es funktioniert für mich ...
||
für Unterabfragen? Ich glaube nicht, dass es für die Unterabfragen erforderlich ist. aber ja, es ist für die primäre Auswahl erforderlich.
select x
? Dies sollte ohne funktionieren. @davidb, Sie haben Recht, dass die Verkettung in der primären inneren Unterabfrage nicht erforderlich ist, sondern alle Spalten als col1, col2 ... usw. aliasiert. ist dort erforderlich.
Bei neueren Versionen von Client-Tools gibt es mehrere Optionen zum Formatieren der Abfrageausgabe. Der Rest besteht darin, es in eine Datei zu spulen oder die Ausgabe je nach Client-Tool als Datei zu speichern. Hier sind einige der Möglichkeiten:
Mit den SQL * Plus-Befehlen können Sie formatieren, um die gewünschte Ausgabe zu erhalten. Verwenden Sie SPOOL, um die Ausgabe in eine Datei zu spoolen .
Beispielsweise,
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>
Alternativ können Sie den neuen Hinweis in SQL Developer verwenden ./*csv*/
/*csv*/
Zum Beispiel in meinem SQL Developer Version 3.2.20.10 :
Jetzt können Sie die Ausgabe in einer Datei speichern.
Verwenden Sie in SQL Developer Version 4.1 den folgenden Befehl wie den Befehl sqlplus und führen Sie ihn als Skript aus. Der Hinweis in der Abfrage ist nicht erforderlich.
SET SQLFORMAT csv
Jetzt können Sie die Ausgabe in einer Datei speichern.
Ich weiß, dass dies ein alter Thread ist, aber ich habe festgestellt, dass niemand die Unterstreichungsoption erwähnt hat, mit der die Unterstreichungen unter den Spaltenüberschriften entfernt werden können.
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;
Es ist grob, aber:
set pagesize 0 linesize 500 trimspool on feedback off echo off
select '"' || empno || '","' || ename || '","' || deptno || '"' as text
from emp
spool emp.csv
/
spool off
Sie können die Abfrage explizit formatieren, um eine begrenzte Zeichenfolge mit folgenden Elementen zu erstellen:
select '"'||foo||'","'||bar||'"'
from tab
Und richten Sie die Ausgabeoptionen entsprechend ein. Optional können Sie mit der COLSEP-Variablen in SQLPlus begrenzte Dateien erstellen, ohne explizit eine Zeichenfolge mit den miteinander verketteten Feldern generieren zu müssen. Sie müssen jedoch Zeichenfolgen in Spalten, die möglicherweise eingebettete Kommazeichen enthalten, in Anführungszeichen setzen.
Verwenden Sie lieber "set colsep" in der sqlplus-Eingabeaufforderung, anstatt den Spaltennamen einzeln zu bearbeiten. Verwenden Sie sed, um die Ausgabedatei zu bearbeiten.
set colsep '","' -- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
Ich habe einmal ein kleines SQL * Plus-Skript geschrieben, das eine CSV (eigentlich eine SSV) verwendet dbms_sql
und dbms_output
erstellt. Sie finden es in meinem Githup-Repository .
Sie sollten sich bewusst sein, dass Werte von Feldern Kommas und Anführungszeichen enthalten können, sodass einige der vorgeschlagenen Antworten nicht funktionieren, da die CSV-Ausgabedatei nicht korrekt ist. Um Anführungszeichen in einem Feld zu ersetzen und durch das doppelte Anführungszeichen zu ersetzen, können Sie die von oracle bereitgestellte REPLACE-Funktion verwenden, um ein einfaches Anführungszeichen in ein doppeltes Anführungszeichen zu ändern.
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
Oder wenn Sie das einfache Anführungszeichen für die Felder möchten:
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()
ist unnötig.
Verwenden Sie vi oder vim, um das SQL zu schreiben, verwenden Sie colsep mit einem Steuerelement-A (in vi und vim steht das Strg-A mit einem Strg-v vor). Stellen Sie sicher, dass die Linien- und Seitengröße auf etwas Rationales eingestellt ist, und aktivieren Sie Trimspool und Trimout.
spule es in eine Datei. Dann...
sed -e 's/,/;/g' -e 's/ *{ctrl-a} */,/g' {spooled file} > output.csv
Das sed Ding kann in ein Skript verwandelt werden. Das "*" vor und nach Strg-A drückt alle nutzlosen Leerzeichen aus. Ist es nicht toll, dass sie sich die Mühe gemacht haben, die HTML-Ausgabe von sqlplus zu aktivieren, aber NICHT native csv ?????
Ich mache es so, weil es Kommas in den Daten behandelt. Ich verwandle sie in Semikolons.
Es gibt ein Problem bei der Verwendung von sqlplus zum Erstellen von CSV-Dateien. Wenn Sie möchten, dass die Spaltenüberschriften nur einmal in der Ausgabe angezeigt werden und Tausende oder Millionen von Zeilen vorhanden sind, können Sie die Seitengröße nicht groß genug einstellen, um keine Wiederholung zu erhalten. Die Lösung besteht darin, mit Seitengröße = 50 zu beginnen und die Überschriften zu analysieren. Anschließend müssen Sie die Auswahl erneut mit Seitengröße = 0 ausführen, um die Daten abzurufen. Siehe Bash-Skript unten:
#!/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
}
Ich habe dieses reine SQLPlus-Skript geschrieben, um Tabellen 1994 in CSV zu sichern.
Wie in den Skriptkommentaren angegeben, hat jemand bei Oracle mein Skript in einen Oracle Support-Hinweis eingefügt, jedoch ohne Zuordnung.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
Das Skript erstellt außerdem eine Steuerdatei und eine Parameterdatei für SQL * LOADER
spool D:\test.txt
select * from emp
spool off
Sie könnten einen CSV-Hinweis verwenden. Siehe folgendes Beispiel:
select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;