Bagaimana cara spool ke file berformat CSV menggunakan SQLPLUS?

143

Saya ingin mengekstrak beberapa pertanyaan ke format output CSV. Sayangnya, saya tidak dapat menggunakan klien SQL mewah atau bahasa apa pun untuk melakukannya. Saya harus menggunakan SQLPLUS.

Bagaimana saya melakukannya?

Daniel C. Sobral
sumber
Tolong, tandai sebagai jawaban yang benar yang diberikan oleh @ Bob. Itu tidak ada perintah spool untuk mencetak file tetapi itu adalah solusi paling sederhana untuk mengekspor data dalam format csv.
rlar

Jawaban:

28

Jika Anda menggunakan 12.2, Anda bisa mengatakannya

set markup csv on
spool myfile.csv
BobC
sumber
Apakah ada yang tahu cara mematikan gema, "set gema mati" yang jelas tampaknya tidak berhasil dengan ini?
Quaternion
Dengan asumsi bahwa ini adalah karena Anda mengeksekusi skrip dan menulis ke file, Anda harus "menonaktifkan termout"
BobC
155

Anda juga bisa menggunakan yang berikut ini, meskipun itu memperkenalkan spasi antar bidang.

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 akan seperti:

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

Ini akan jauh lebih membosankan daripada mengetik semua bidang dan menggabungkannya dengan koma. Anda bisa menindaklanjutinya dengan skrip sed sederhana untuk menghapus spasi putih yang muncul sebelum koma, jika Anda mau.

Sesuatu seperti ini mungkin bekerja ... (skill sed saya sangat berkarat, jadi ini mungkin perlu bekerja)

sed 's/\s+,/,/' myfile.csv 
Gabe
sumber
Tanda "," tidak ada dalam baris te colsep. Headep off dan linesize X mungkin berguna. Edit jawabannya dan saya akan menerimanya.
Daniel C. Sobral
5
Perintah sed adalah: cat myfile.csv | sed -e 's / [\ t] * | / | / g; s / | [] * / | / g '> myfile.csv. Bagaimanapun, Oracle benar-benar menyebalkan.
Stan
2
Dan untuk mendapatkan header dengan nama kolom menggunakan set pagesize 1000bukannya 0. Dalam komentar saya sebelumnya, Anda tidak dapat mengarahkan ke file yang sama: cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv.
Stan
1
Saya disaring kekosongan dan strip digunakan untuk garis bawah dengan grepdan trseperti ini grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013
1
@slayernoah perintah spool dapat mengambil jalur direktori dan nama file, sehingga Anda dapat menentukan dengan tepat di mana file output akan ditempatkan. Kalau tidak, itu akan tergantung pada lokasi di mana Anda mengeksekusi skrip.
Gabe
35

Saya menggunakan perintah ini untuk skrip yang mengekstrak data untuk tabel dimensi (DW). Jadi, saya menggunakan sintaks berikut:

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

Dan bekerja. Saya tidak menggunakan sed untuk memformat file output.

Hallison Batista
sumber
24

Saya melihat masalah yang sama ...

Saya perlu spool file CSV dari SQLPLUS, tetapi hasilnya memiliki 250 kolom.

Apa yang saya lakukan untuk menghindari pemformatan output SQLPLUS yang mengganggu:

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

masalahnya adalah Anda akan kehilangan nama header kolom ...

Anda dapat menambahkan ini:

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

Saya tahu ini agak hardcore, tapi itu bekerja untuk saya ...

Karlos
sumber
Apakah kita perlu ||untuk subquery juga ?, Saya rasa itu tidak diperlukan untuk subquery. tapi ya itu diperlukan untuk pemilihan utama.
davidb
Untuk apa ekstra luar select x? Ini seharusnya bekerja tanpanya. @davidb, Anda benar bahwa rangkaian tidak diperlukan dalam subquery bagian dalam primer, tetapi aliasing semua kolom sebagai col1, col2 ... dll. diperlukan di sana.
Amit Naidu
18

Dengan versi alat klien yang lebih baru, ada beberapa opsi untuk memformat output kueri. Sisanya adalah untuk menggulungnya ke file atau menyimpan output sebagai file tergantung pada alat klien. Berikut ini beberapa caranya:

  • SQL * Plus

Menggunakan perintah SQL * Plus Anda bisa memformat untuk mendapatkan output yang Anda inginkan. Gunakan SPOOL untuk menggulung output ke file.

Sebagai contoh,

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>
  • Versi Pengembang SQL sebelum 4.1

Atau, Anda bisa menggunakan petunjuk baru di SQL Developer ./*csv*/

/*csv*/

Misalnya, dalam Versi Pengembang SQL saya 3.2.20.10 :

masukkan deskripsi gambar di sini

Sekarang Anda bisa menyimpan output ke file.

  • Pengembang SQL Versi 4.1

Baru di SQL Developer versi 4.1, gunakan perintah berikut seperti sqlplus dan jalankan sebagai skrip. Tidak perlu petunjuk dalam kueri.

SET SQLFORMAT csv

Sekarang Anda bisa menyimpan output ke file.

Lalit Kumar B
sumber
12

Saya tahu ini adalah utas lama, namun saya perhatikan bahwa tidak ada yang menyebutkan opsi garis bawah, yang dapat menghapus garis bawah di bawah judul kolom.

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;
Dokter
sumber
Tangkapan bagus pada opsi garis bawah, membutuhkan yang itu.
knockando
Sangat menyenangkan jika Anda ingin csv dengan baris atas yang berisi judul / judul untuk setiap kolom. Ini akan membantu siapa saja yang mungkin ingin melihat file csv, dan mencari tahu apa yang mereka lihat, dll ...
Doc
10

Itu mentah, tapi:

set pagesize 0 linesize 500 trimspool on feedback off echo off

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

spool emp.csv
/
spool off
Tony Andrews
sumber
7

Anda dapat secara eksplisit memformat kueri untuk menghasilkan string yang dibatasi dengan sesuatu di sepanjang baris:

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

Dan mengatur opsi output yang sesuai. Sebagai pilihan, variabel COLSEP pada SQLPlus akan memungkinkan Anda menghasilkan file yang dibatasi tanpa harus secara eksplisit menghasilkan string dengan bidang yang digabungkan bersama. Namun, Anda harus memberi tanda kutip di sekitar string pada kolom apa pun yang mungkin berisi karakter koma yang disematkan.

ConcernedOfTunbridgeWells
sumber
4

lebih suka menggunakan "set colsep" di sqlplus prompt daripada mengedit nama col satu per satu. Gunakan sed untuk mengedit file output.

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

Saya pernah menulis skrip SQL * Plus kecil yang menggunakan dbms_sqldan dbms_outputuntuk membuat csv (sebenarnya ssv). Anda dapat menemukannya di repositori githup saya .

René Nyffenegger
sumber
2

Anda harus menyadari bahwa nilai-nilai bidang dapat berisi koma dan karakter kutipan, sehingga beberapa jawaban yang disarankan tidak akan berfungsi, karena file output CSV tidak benar. Untuk mengganti karakter kutip dalam bidang, dan menggantinya dengan karakter kutip ganda, Anda dapat menggunakan fungsi REPLACE yang disediakan oracle, untuk mengubah kutipan tunggal menjadi kutipan ganda.

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

Atau, jika Anda ingin karakter kutipan tunggal untuk bidang:

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
Rob Heusdens
sumber
Itu trim()tidak perlu.
Amit Naidu
1

Gunakan vi atau vim untuk menulis sql, gunakan colsep dengan kontrol-A (in vi dan vim mendahului ctrl-A dengan ctrl-v). Pastikan untuk mengatur garis dan halaman ke sesuatu yang rasional dan nyalakan trimspool dan trimout.

gulung ke file. Kemudian...

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

Hal sed itu bisa dijadikan naskah. "*" Sebelum dan sesudah ctrl-A meremas semua ruang yang tidak berguna. Bukankah luar biasa bahwa mereka repot-repot mengaktifkan output html dari sqlplus tetapi BUKAN csv asli ?????

Saya melakukannya dengan cara ini karena menangani koma dalam data. Saya mengubahnya menjadi semi-titik dua.

Charles Stepp
sumber
3
Ini gagal dalam tes "Saya harus menggunakan SQLPlus".
Daniel C. Sobral
0

Ada masalah menggunakan sqlplus untuk membuat file csv. Jika Anda ingin tajuk kolom hanya sekali dalam output dan ada ribuan atau jutaan baris, Anda tidak dapat mengatur ukuran halaman cukup besar untuk tidak mendapatkan pengulangan. Solusinya adalah mulai dengan pagesize = 50 dan parsing header, lalu keluarkan pilih lagi dengan pagesize = 0 untuk mendapatkan data. Lihat skrip bash di bawah ini:

#!/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
}
Larry R. Irwin
sumber
0

Saya menulis skrip murni SQLPlus ini untuk membuang tabel ke CSV pada tahun 1994.

Seperti tercantum dalam komentar skrip, seseorang di Oracle memasukkan skrip saya ke dalam catatan Dukungan Oracle, tetapi tanpa atribusi.

https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql

Script juga membangun file kontrol dan file parameter untuk SQL * LOADER

Jared Still
sumber
-1
spool D:\test.txt

    select * from emp
    
    spool off
Satheeshkumar P
sumber
-3

Anda bisa menggunakan petunjuk csv. Lihat contoh berikut:

select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;
Adilson Silva
sumber