ฉันจะสปูลไปยังไฟล์ที่จัดรูปแบบ CSV โดยใช้ SQLPLUS ได้อย่างไร


143

ฉันต้องการแยกข้อความค้นหาบางส่วนเป็นรูปแบบเอาต์พุต CSV น่าเสียดายที่ฉันไม่สามารถใช้ไคลเอนต์ SQL แฟนซีหรือภาษาใดก็ได้ ฉันต้องใช้ SQLPLUS

ฉันต้องทำอย่างไร?


กรุณาทำเครื่องหมายว่าถูกต้องตอบโดย @BobC ไม่มีคำสั่ง spool ในการพิมพ์ไฟล์ แต่เป็นวิธีที่ง่ายที่สุดในการส่งออกข้อมูลในรูปแบบ csv
rlar

คำตอบ:


28

หากคุณใช้ 12.2 คุณสามารถพูดได้

set markup csv on
spool myfile.csv

ไม่มีใครรู้วิธีปิด echo คุณดูเหมือน "set echo off" ที่เห็นได้ชัดจะไม่สามารถใช้งานได้หรือไม่
Quaternion

สมมติว่านี่เป็นเพราะคุณกำลังเรียกใช้งานสคริปต์และเขียนไปยังไฟล์คุณควรเพียงแค่ "ตั้งค่าการเลิกจ้างออก"
BobC

155

คุณสามารถใช้สิ่งต่อไปนี้แม้ว่าจะมีการเว้นวรรคระหว่างฟิลด์

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;

ผลผลิตจะเป็นเช่น:

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

นี่จะน่าเบื่อน้อยกว่าการพิมพ์ฟิลด์ทั้งหมดและต่อคอมม่ากับคอมม่า คุณสามารถติดตามด้วยสคริปต์แบบง่ายเพื่อลบช่องว่างที่ปรากฏก่อนเครื่องหมายจุลภาคหากคุณต้องการ

บางสิ่งบางอย่างเช่นนี้อาจทำงานได้ ... (ทักษะความสุขุมของฉันเป็นสนิมมากดังนั้นสิ่งนี้จะต้องทำงาน)

sed 's/\s+,/,/' myfile.csv 

"," หายไปในบรรทัด te colsep นอกจากนี้ Headsep off และ Linesize X ก็น่าจะมีประโยชน์เช่นกัน แก้ไขคำตอบและฉันจะยอมรับมัน
Daniel C. Sobral

5
คำสั่ง sed คือ: cat myfile.csv | sed -e 's / [\ t] * | / | / g; s / | [] * / | / g '> myfile.csv อย่างไรก็ตามออราเคิลก็แย่จริงๆ
Stan

2
และเพื่อให้ได้ส่วนหัวที่มีชื่อคอลัมน์ใช้set pagesize 1000แทน 0 cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csvในความคิดเห็นก่อนหน้าของฉันคุณจะไม่สามารถเปลี่ยนเส้นทางไปยังไฟล์เดียวกัน:
Stan

1
ฉันกรองออกช่องว่างและขีดกลางที่ใช้ในการขีดเส้นใต้ด้วยgrepและเช่นนี้tr grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
ixe013

1
@slayernoah คำสั่ง spool สามารถใช้พา ธ ไดเร็กทอรีและชื่อไฟล์เพื่อให้คุณสามารถระบุตำแหน่งที่จะวางไฟล์เอาต์พุต มิฉะนั้นจะขึ้นอยู่กับตำแหน่งที่คุณเรียกใช้งานสคริปต์
Gabe

35

ฉันใช้คำสั่งนี้สำหรับสคริปต์ที่แยกข้อมูลสำหรับตารางมิติ (DW) ดังนั้นฉันใช้ไวยากรณ์ต่อไปนี้:

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

และผลงาน ฉันไม่ได้ใช้เพื่อจัดรูปแบบไฟล์เอาต์พุต


24

ฉันเห็นปัญหาที่คล้ายกัน ...

ฉันต้องการสปูลไฟล์ CSV จาก SQLPLUS แต่ผลลัพธ์มี 250 คอลัมน์

สิ่งที่ฉันทำเพื่อหลีกเลี่ยงการจัดรูปแบบเอาต์พุต SQLPLUS ที่น่ารำคาญ:

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

ปัญหาคือคุณจะสูญเสียชื่อส่วนหัวของคอลัมน์ ...

คุณสามารถเพิ่มสิ่งนี้:

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

ฉันรู้ว่ามันไม่ยอมใครง่ายๆนะ แต่มันใช้ได้กับฉัน ...


เราต้องการ||คิวรีย่อยด้วยหรือไม่ฉันไม่คิดว่ามันจำเป็นสำหรับคิวรีย่อย แต่ใช่มันเป็นสิ่งจำเป็นสำหรับการเลือกหลัก
davidb

ข้างนอกพิเศษselect xสำหรับคืออะไร? สิ่งนี้จะทำงานได้โดยปราศจากมัน @davidb คุณถูกต้องที่การต่อข้อมูลไม่จำเป็นในเคียวรี่ย่อยภายในหลัก แต่ใช้นามแฝงคอลัมน์ทั้งหมดเป็น col1, col2 ... ฯลฯ จำเป็นต้องมี
Amit Naidu

18

ด้วยเครื่องมือไคลเอนต์รุ่นใหม่กว่ามีหลายตัวเลือกในการจัดรูปแบบผลลัพธ์แบบสอบถาม ส่วนที่เหลือคือการสปูลไปยังไฟล์หรือบันทึกผลลัพธ์เป็นไฟล์ขึ้นอยู่กับเครื่องมือของลูกค้า นี่คือบางวิธี:

  • SQL * Plus

การใช้คำสั่ง SQL * Plus คุณสามารถฟอร์แมตเพื่อให้ได้ผลลัพธ์ที่คุณต้องการ ใช้SPOOLเพื่อสพูลเอาต์พุตไปยังไฟล์

ตัวอย่างเช่น,

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 เวอร์ชั่นก่อน 4.1

หรือคุณสามารถใช้ใหม่คำใบ้ในSQL Developer/*csv*/

/*csv*/

ตัวอย่างเช่นในSQL Developer เวอร์ชัน 3.2.20.10ของฉัน:

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้คุณสามารถบันทึกผลลัพธ์ลงในไฟล์

  • SQL Developer เวอร์ชั่น 4.1

ใหม่ใน SQL Developer เวอร์ชัน 4.1 ใช้คำสั่ง sqlplus ดังต่อไปนี้และเรียกใช้เป็นสคริปต์ ไม่จำเป็นต้องมีคำใบ้ในแบบสอบถาม

SET SQLFORMAT csv

ตอนนี้คุณสามารถบันทึกผลลัพธ์ลงในไฟล์


12

ฉันรู้ว่านี่เป็นเธรดเก่า แต่ฉันสังเกตเห็นว่าไม่มีใครพูดถึงตัวเลือกขีดเส้นใต้ซึ่งสามารถลบขีดเส้นใต้ใต้ส่วนหัวคอลัมน์ได้

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;

จับได้ดีบนตัวเลือกขีดเส้นใต้จำเป็นต้องมี
knockando

มันดีถ้าคุณต้องการ csv ที่มีแถวบนสุดที่มีชื่อ / ส่วนหัวสำหรับแต่ละคอลัมน์ มันจะช่วยให้ทุกคนที่อาจต้องการดูไฟล์ csv และหาสิ่งที่พวกเขากำลังมองหาและอื่น ๆ ...
Doc


7

คุณสามารถจัดรูปแบบเคียวรีอย่างชัดเจนเพื่อสร้างสตริงที่คั่นด้วยบางสิ่งตามแนวของ:

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

และตั้งค่าตัวเลือกเอาต์พุตตามความเหมาะสม ในฐานะตัวเลือกตัวแปร COLSEP บน SQLPlus จะช่วยให้คุณสร้างไฟล์ที่มีการคั่นโดยไม่ต้องสร้างสตริงอย่างชัดเจนโดยมีฟิลด์ที่ต่อกันเข้าด้วยกัน อย่างไรก็ตามคุณจะต้องใส่เครื่องหมายคำพูดล้อมรอบสตริงในคอลัมน์ใด ๆ ที่อาจมีอักขระเครื่องหมายจุลภาคฝังอยู่


4

ชอบที่จะใช้ "set colsep" ในพรอมต์ sqlplus แทนการแก้ไขชื่อ col หนึ่งโดยหนึ่ง ใช้ sed เพื่อแก้ไขไฟล์เอาต์พุต

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

3

ฉันเคยเขียนสคริปต์ SQL * Plus เล็กน้อยที่ใช้dbms_sqlและdbms_outputสร้าง csv (จริง ๆ แล้วเป็น ssv) คุณสามารถค้นหาได้ในพื้นที่เก็บข้อมูล githup ของฉัน


2

คุณควรทราบว่าค่าของฟิลด์อาจมีเครื่องหมายจุลภาคและอักขระอัญประกาศดังนั้นคำตอบที่แนะนำบางข้ออาจใช้ไม่ได้เนื่องจากไฟล์เอาต์พุต CSV ไม่ถูกต้อง ในการแทนที่อักขระอัญประกาศในเขตข้อมูลและแทนที่ด้วยอักขระอัญประกาศคู่คุณสามารถใช้ฟังก์ชัน REPLACE ที่ oracle จัดเตรียมไว้เพื่อเปลี่ยนอัญประกาศเดี่ยวเป็นอัญประกาศคู่

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

หรือถ้าคุณต้องการอักขระเครื่องหมายคำพูดเดี่ยวสำหรับฟิลด์:

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()ไม่จำเป็น
Amit Naidu

1

ใช้ vi หรือ vim เพื่อเขียน sql ใช้ colsep กับ control-A (ใน vi และ vim นำหน้า ctrl-A ด้วย ctrl-v) ตรวจสอบให้แน่ใจว่าได้ตั้งค่าขนาดเส้นและหน้าให้เป็นสิ่งที่มีเหตุผลและเปิด trimspool และ trimout

สปูลออกเป็นไฟล์ จากนั้น ...

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

สิ่งที่ไม่ดีสามารถเปลี่ยนเป็นสคริปต์ได้ "*" ก่อนและหลัง ctrl-A บีบพื้นที่ว่างเปล่าทั้งหมดออก มันดีใช่ไหมที่พวกเขาใส่ใจที่จะเปิดใช้งานเอาต์พุต html จาก sqlplus แต่ไม่ใช่ csv ดั้งเดิม ?????

ฉันทำอย่างนี้เพราะจัดการกับเครื่องหมายจุลภาคในข้อมูล ฉันเปลี่ยนมันเป็นเซมิโคลอน


3
สิ่งนี้ล้มเหลวในการทดสอบ "ฉันต้องใช้ SQLPlus"
Daniel C. Sobral

0

มีปัญหาในการใช้ sqlplus เพื่อสร้างไฟล์ csv หากคุณต้องการให้ส่วนหัวคอลัมน์เพียงครั้งเดียวในผลลัพธ์และมีหลายพันหรือหลายแถวคุณไม่สามารถกำหนดขนาดหน้าให้ใหญ่พอที่จะไม่ทำซ้ำได้ วิธีแก้ปัญหาคือเริ่มต้นด้วย pagesize = 50 และแยกส่วนหัวออกแล้วเลือกส่วนอีกครั้งด้วย pagesize = 0 เพื่อรับข้อมูล ดูสคริปต์ทุบตีด้านล่าง:

#!/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
}

0

ฉันเขียนสคริปต์ SQLPlus นี้เพื่อถ่ายโอนตารางไปยัง CSV ในปี 1994

ดังที่ระบุไว้ในความคิดเห็นของสคริปต์บางคนที่ Oracle ใส่สคริปต์ของฉันลงในบันทึกการสนับสนุนของ Oracle แต่ไม่มีการระบุแหล่งที่มา

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

สคริปต์ยังสร้างไฟล์ควบคุมและไฟล์พารามิเตอร์สำหรับ SQL * LOADER



-3

คุณสามารถใช้คำใบ้ csv ดูตัวอย่างต่อไปนี้:

select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.