Wie spule ich mit SQLPLUS in eine CSV-formatierte Datei?


143

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?


Bitte markieren Sie die Antwort von @BobC als richtig. Es fehlt der Befehl spool zum Drucken der Datei, aber es ist die einfachste Lösung, Daten im CSV-Format zu exportieren.
Rlar

Antworten:


28

Wenn Sie 12.2 verwenden, können Sie einfach sagen

set markup csv on
spool myfile.csv

Weiß jemand, wie man das Echo ausschaltet, das offensichtliche "Echo ausschalten" scheint damit nicht zu funktionieren?
Quaternion

Angenommen, dies liegt daran, dass Sie ein Skript ausführen und in eine Datei schreiben, sollten Sie einfach "termout off" setzen
BobC

155

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 

Das "," fehlt in der Spalte. Auch Headsep Off und Liniengröße X sind wahrscheinlich nützlich. Bearbeiten Sie die Antwort und ich werde es akzeptieren.
Daniel C. Sobral

5
Der Befehl sed lautet: cat myfile.csv | sed -es / [\ t] * | / | / g; s / | [] * / | / g '> myfile.csv. Wie auch immer, Oracle ist wirklich scheiße.
Stan

2
Und um einen Header mit den Spaltennamen zu erhalten, verwenden Sie set pagesize 1000anstelle 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.
Stan

1
Ich filtriert , um die Zuschnitte und die zu unterstreichen verwendet Striche mit grepund trwie diese grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013

1
@slayernoah Der Befehl spool kann einen Verzeichnispfad und einen Dateinamen annehmen, sodass Sie genau angeben können, wo die Ausgabedatei abgelegt werden soll. Andernfalls hängt es vom Speicherort ab, an dem Sie das Skript ausführen.
Gabe

35

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.


24

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 ...


brauchen wir auch ||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.
Davidb

Wofür ist das zusätzliche Äußere 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.
Amit Naidu

18

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:

  • SQL * Plus

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>
  • SQL Developer Version vor 4.1

Alternativ können Sie den neuen Hinweis in SQL Developer verwenden ./*csv*/

/*csv*/

Zum Beispiel in meinem SQL Developer Version 3.2.20.10 :

Geben Sie hier die Bildbeschreibung ein

Jetzt können Sie die Ausgabe in einer Datei speichern.

  • SQL Developer Version 4.1

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.


12

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;

Netter Fang bei der Unterstreichungsoption, brauchte diesen.
Knockando

Es ist schön, wenn Sie eine CSV mit einer oberen Zeile möchten, die den Titel / die Überschriften für jede Spalte enthält. Es würde jedem helfen, der die CSV-Datei anzeigen und herausfinden möchte, was er gerade sieht, usw.
Doc

10

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

7

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.


4

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


2

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

Das trim()ist unnötig.
Amit Naidu

1

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.


3
Dies schlägt den Test "Ich muss SQLPlus verwenden" fehl.
Daniel C. Sobral

0

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
}



-3

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;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.