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?
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?
Jawaban:
Jika Anda menggunakan 12.2, Anda bisa mengatakannya
set markup csv on
spool myfile.csv
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
set pagesize 1000
bukannya 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
.
grep
dan tr
seperti ini grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.
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.
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 ...
||
untuk subquery juga ?, Saya rasa itu tidak diperlukan untuk subquery. tapi ya itu diperlukan untuk pemilihan utama.
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.
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:
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>
Atau, Anda bisa menggunakan petunjuk baru di SQL Developer ./*csv*/
/*csv*/
Misalnya, dalam Versi Pengembang SQL saya 3.2.20.10 :
Sekarang Anda bisa menyimpan output ke file.
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.
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;
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
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.
Saya pernah menulis skrip SQL * Plus kecil yang menggunakan dbms_sql
dan dbms_output
untuk membuat csv (sebenarnya ssv). Anda dapat menemukannya di repositori githup saya .
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
trim()
tidak perlu.
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.
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
}
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
spool D:\test.txt
select * from emp
spool off
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;