如何使用SQLPLUS假脱机到CSV格式的文件?

如何使用SQLPLUS假脱机到CSV格式的文件?,sql,oracle,csv,sqlplus,Sql,Oracle,Csv,Sqlplus,我想将一些查询提取为CSV输出格式。不幸的是,我不能使用任何高级SQL客户机或任何语言来完成这项工作。我必须使用SQLPLUS 如何操作?您可以显式格式化查询,以生成一个带分隔符的字符串,其中包含以下内容: select '"'||foo||'","'||bar||'"' from tab 并根据需要设置输出选项。作为一个选项,SQLPlus上的COLSEP变量将允许您生成带分隔符的文件,而无需显式生成字段连接在一起的字符串。但是,您必须在任何可能包含嵌入逗号字符的列上的字符串周围加引号。

我想将一些查询提取为CSV输出格式。不幸的是,我不能使用任何高级SQL客户机或任何语言来完成这项工作。我必须使用SQLPLUS


如何操作?

您可以显式格式化查询,以生成一个带分隔符的字符串,其中包含以下内容:

select '"'||foo||'","'||bar||'"'
  from tab
并根据需要设置输出选项。作为一个选项,SQLPlus上的COLSEP变量将允许您生成带分隔符的文件,而无需显式生成字段连接在一起的字符串。但是,您必须在任何可能包含嵌入逗号字符的列上的字符串周围加引号。

这很粗糙,但是:

set pagesize 0 linesize 500 trimspool on feedback off echo off

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

spool emp.csv
/
spool off

您也可以使用以下命令,尽管它在字段之间引入了空格

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脚本来删除逗号前的空白

像这样的东西可能会有用…(我的sed技能非常生疏,所以这可能需要改进)


我看到了一个类似的问题

我需要从SQLPLUS中假脱机CSV文件,但输出有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
我知道它有点硬,但对我来说很有用…

更喜欢在sqlplus提示符中使用“set colsep”,而不是逐个编辑列名称。使用sed编辑输出文件

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

我将此命令用于提取维度表(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
set colsep'|'
激起回声
引发反馈
设置行大小1000
将页面大小设置为0
设置sqlprompt“”
打开阀芯
顶起
滑阀输出.dat
选择“|”、.*、|”
从…起
哪里
停止输出

而且有效。我不使用sed来格式化输出文件。

我曾经编写过一个小的SQL*Plus脚本,它使用
dbms\u SQL
dbms\u output
来创建一个csv(实际上是一个ssv)。您可以找到它。

使用vi或vim编写sql,使用colsep和控件a(在vi和vim中,在ctrl-a之前加上ctrl-v)。确保将linesize和pagesize设置为合理值,并启用trimspool和trimout

set colsep '","'     -- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
将其假脱机成文件。 然后

sed的东西可以变成脚本。ctrl-A前后的“*”将挤出所有无用的空格。他们费心从sqlplus而不是本地csv启用html输出,这不是很好吗


我这样做是因为它处理数据中的逗号。我将它们转换为分号。

对于较新版本的客户端工具,有多个选项可以格式化查询输出。其余的步骤是根据客户机工具将其假脱机到文件或将输出另存为文件。以下是几种方法:

  • SQL*Plus
使用SQL*Plus命令,您可以格式化以获得所需的输出。使用假脱机将输出假脱机到文件

比如说,

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开发人员版本4.1之前的版本
或者,您可以在SQL Developer中使用新的
/*csv*/
提示

/*csv*/
例如,在我的SQL Developer 3.2.20.10版中:

现在可以将输出保存到文件中

  • SQL开发人员版本4.1
在SQLDeveloperVersion4.1中新增了以下命令,与sqlplus命令一样使用,并作为脚本运行。查询中不需要提示

SET SQLFORMAT csv

现在您可以将输出保存到文件中。

您可以使用csv提示。请参见以下示例:

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

我知道这是一个旧的线程,但是我注意到没有人提到下划线选项,它可以删除列标题下的下划线

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;

您应该知道,字段的值可能包含逗号和引号字符,因此一些建议的答案不起作用,因为CSV输出文件不正确。 要替换字段中的引号字符并将其替换为双引号字符,可以使用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

如果您使用的是12.2,您可以简单地说

set markup csv on
spool myfile.csv

使用sqlplus创建csv文件时出现问题。如果您希望列标题在输出中只出现一次,并且有数千行或数百万行,则不能将pagesize设置得足够大,以避免重复。 解决方案是从pagesize=50开始,解析出标题,然后再次发出选择,pagesize=0以获取数据。请参见下面的bash脚本:

#!/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
}
#/bin/bash
FOLDER=“csvdata\u mydb”
CONN=“192.168.100.11:1521/mydb0023.world”
CNT=0376
ORD=“0376”
TABLE=“我的附件”
sqlplus-L logn/pswd@/${CONN}./${ORD}${TABLE}.headers
}
sqlplus-L logn/pswd@/${CONN}${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
}

我在1994年编写了这个纯SQLPlus脚本,将表转储到CSV

正如脚本注释中所指出的,Oracle的某个人将我的脚本放在Oracle支持说明中,但没有署名


该脚本还为SQL*加载器构建了一个控制文件和一个参数文件,te colsep行中缺少“.”。此外,头枕关闭和线条尺寸X可能会很有用。编辑答案,我会接受它。sed命令是:cat myfile.csv | sed-e's/[\t]*|/|/g;s/|[]*/|/g'>myfile.csv。不管怎么说,Oracle真的很烂。要获得带有列名的标题,请使用
设置pagesize 1000
而不是0。在我之前的评论中,您不能重定向到同一个文件:
cat myfile.csv | sed-e的/[\t]*|/|/g;s/|[]*/|/g'>我的其他文件.csv
。我过滤掉了
spool D:\test.txt

    select * from emp
    
    spool off
spool D:\test.txt

    select * from emp
    
    spool off