Tôi muốn trích xuất một số truy vấn sang định dạng đầu ra CSV. Thật không may, tôi không thể sử dụng bất kỳ máy khách SQL ưa thích hoặc bất kỳ ngôn ngữ nào để làm điều đó. Tôi phải sử dụng SQLPLUS.
Tôi phải làm nó như thế nào?
Tôi muốn trích xuất một số truy vấn sang định dạng đầu ra CSV. Thật không may, tôi không thể sử dụng bất kỳ máy khách SQL ưa thích hoặc bất kỳ ngôn ngữ nào để làm điều đó. Tôi phải sử dụng SQLPLUS.
Tôi phải làm nó như thế nào?
Câu trả lời:
Nếu bạn đang sử dụng 12.2, bạn có thể nói một cách đơn giản
set markup csv on
spool myfile.csv
Bạn cũng có thể sử dụng như sau, mặc dù nó giới thiệu khoảng trắng giữa các trường.
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;
Đầu ra sẽ như sau:
TABLE_PRIVILEGE_MAP ,SYSTEM
SYSTEM_PRIVILEGE_MAP ,SYSTEM
STMT_AUDIT_OPTION_MAP ,SYSTEM
DUAL ,SYSTEM
...
Điều này sẽ ít tẻ nhạt hơn nhiều so với việc gõ ra tất cả các trường và nối chúng với dấu phẩy. Bạn có thể theo dõi với một tập lệnh sed đơn giản để xóa khoảng trắng xuất hiện trước dấu phẩy, nếu bạn muốn.
Một cái gì đó như thế này có thể hoạt động ... (kỹ năng sed của tôi rất gỉ, vì vậy điều này có thể sẽ cần làm việc)
sed 's/\s+,/,/' myfile.csv
set pagesize 1000
thay vì 0. Trong nhận xét trước đây của tôi, bạn không thể chuyển hướng đến cùng một tệp : cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv
.
grep
và tr
như thế này grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.
Tôi sử dụng lệnh này cho các tập lệnh trích xuất dữ liệu cho các bảng chiều (DW). Vì vậy, tôi sử dụng cú pháp sau:
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
Và hoạt động. Tôi không sử dụng sed để định dạng tệp đầu ra.
Tôi thấy một vấn đề tương tự ...
Tôi cần phải lưu tệp CSV từ SQLPLUS, nhưng đầu ra có 250 cột.
Những gì tôi đã làm để tránh định dạng đầu ra SQLPLUS gây phiền nhiễu:
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
vấn đề là bạn sẽ mất tên tiêu đề cột ...
bạn có thể thêm cái này:
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
Tôi biết nó hơi khó, nhưng nó hiệu quả với tôi ...
||
cho truy vấn con không?, tôi không nghĩ rằng nó là bắt buộc cho các truy vấn con. nhưng có nó là cần thiết cho lựa chọn chính.
select x
để làm gì? Điều này sẽ làm việc mà không có nó. @davidb, bạn đã đúng rằng không cần phải ghép nối trong truy vấn con bên trong chính, nhưng đặt bí danh cho tất cả các cột là col1, col2 ... vv. được yêu cầu ở đó.
Với các phiên bản mới hơn của công cụ máy khách, có nhiều tùy chọn để định dạng đầu ra truy vấn. Phần còn lại là để lưu nó vào một tệp hoặc lưu kết quả đầu ra dưới dạng tệp tùy thuộc vào công cụ máy khách. Dưới đây là một vài cách:
Sử dụng các lệnh SQL * Plus, bạn có thể định dạng để có đầu ra mong muốn. Sử dụng SPOOL để lưu kết quả đầu ra vào một tệp.
Ví dụ,
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>
Ngoài ra, bạn có thể sử dụng gợi ý mới trong SQL Developer ./*csv*/
/*csv*/
Ví dụ: trong SQL Developer phiên bản 3.2.20.10 của tôi :
Bây giờ bạn có thể lưu đầu ra vào một tập tin.
Mới trong SQL Developer phiên bản 4.1, sử dụng lệnh sau giống như lệnh sqlplus và chạy dưới dạng tập lệnh. Không cần gợi ý trong truy vấn.
SET SQLFORMAT csv
Bây giờ bạn có thể lưu đầu ra vào một tập tin.
Tôi biết đây là một chủ đề cũ, tuy nhiên tôi nhận thấy rằng không ai đề cập đến tùy chọn gạch chân, có thể loại bỏ các gạch chân dưới tiêu đề cột.
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;
Thật thô thiển, nhưng:
set pagesize 0 linesize 500 trimspool on feedback off echo off
select '"' || empno || '","' || ename || '","' || deptno || '"' as text
from emp
spool emp.csv
/
spool off
Bạn có thể định dạng rõ ràng truy vấn để tạo ra một chuỗi được phân tách bằng một cái gì đó dọc theo dòng:
select '"'||foo||'","'||bar||'"'
from tab
Và thiết lập các tùy chọn đầu ra khi thích hợp. Như một tùy chọn, biến COLSEP trên SQLPlus sẽ cho phép bạn tạo các tệp được phân tách mà không cần phải tạo một chuỗi rõ ràng với các trường được nối với nhau. Tuy nhiên, bạn sẽ phải đặt dấu ngoặc kép quanh các chuỗi trên bất kỳ cột nào có thể chứa các ký tự dấu phẩy được nhúng.
Tôi đã từng viết một đoạn script SQL * Plus nhỏ sử dụng dbms_sql
và dbms_output
để tạo một csv (thực ra là một ssv). Bạn có thể tìm thấy nó trên kho githup của tôi .
Bạn nên lưu ý rằng các giá trị của các trường có thể chứa dấu phẩy và ký tự trích dẫn, vì vậy một số câu trả lời được đề xuất sẽ không hoạt động, vì tệp đầu ra CSV sẽ không chính xác. Để thay thế các ký tự trích dẫn trong một trường và thay thế nó bằng ký tự trích dẫn kép, bạn có thể sử dụng chức năng REPLACE mà oracle cung cấp, để thay đổi một trích dẫn thành trích dẫn kép.
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
Hoặc, nếu bạn muốn ký tự trích dẫn cho các trường:
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()
không cần thiết.
Sử dụng vi hoặc vim để viết sql, sử dụng colsep với control-A (trong vi và vim đứng trước ctrl-A với ctrl-v). Hãy chắc chắn để đặt kích thước đường thẳng và kích thước trang thành một cái gì đó hợp lý và bật trimspool và trimout.
spool nó ra một tập tin. Sau đó...
sed -e 's/,/;/g' -e 's/ *{ctrl-a} */,/g' {spooled file} > output.csv
Điều đó sed có thể được biến thành một kịch bản. "*" Trước và sau ctrl-A sẽ loại bỏ tất cả các khoảng trống vô dụng. Chẳng phải thật tuyệt khi họ bận tâm kích hoạt đầu ra html từ sqlplus nhưng KHÔNG phải csv bản địa ?????
Tôi làm theo cách này vì nó xử lý dấu phẩy trong dữ liệu. Tôi biến chúng thành dấu chấm phẩy.
Có một vấn đề khi sử dụng sqlplus để tạo tập tin csv. Nếu bạn muốn các tiêu đề cột chỉ một lần trong đầu ra và có hàng ngàn hoặc hàng triệu hàng, bạn không thể đặt kích thước trang đủ lớn để không lặp lại. Giải pháp là bắt đầu với Pagesize = 50 và phân tích các tiêu đề, sau đó đưa ra lựa chọn một lần nữa với Pagesize = 0 để lấy dữ liệu. Xem tập lệnh bash bên dưới:
#!/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
}
Tôi đã viết tập lệnh SQLPlus hoàn toàn này để chuyển các bảng sang CSV vào năm 1994.
Như đã lưu ý trong các nhận xét về tập lệnh, một người nào đó tại Oracle đã đặt tập lệnh của tôi vào một ghi chú Hỗ trợ của Oracle, nhưng không có sự ghi nhận.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
Kịch bản cũng xây dựng tệp điều khiển và tệp tham số cho SQL * LOADER
spool D:\test.txt
select * from emp
spool off
Bạn có thể sử dụng gợi ý csv. Xem ví dụ sau:
select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;