¿Cómo puedo poner en cola un archivo con formato CSV usando SQLPLUS?

143

Quiero extraer algunas consultas a un formato de salida CSV. Desafortunadamente, no puedo usar ningún cliente SQL sofisticado ni ningún idioma para hacerlo. Debo usar SQLPLUS.

¿Cómo lo hago?

Daniel C. Sobral
fuente
Por favor, marque como correcta la respuesta dada por @BobC. Falta el comando spool para imprimir el archivo, pero es la solución más simple para exportar datos en formato csv.
rlar

Respuestas:

28

Si está utilizando 12.2, simplemente puede decir

set markup csv on
spool myfile.csv
BobC
fuente
¿Alguien sabe cómo apagar el eco, el obvio "set echo off" no parece funcionar con esto?
Quaternion el
Suponiendo que esto se debe a que está ejecutando un script y escribiendo en un archivo, simplemente debe "desactivar el término"
BobC
155

También podría usar lo siguiente, aunque introduce espacios entre campos.

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;

La salida será como:

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

Esto sería mucho menos tedioso que escribir todos los campos y concatenarlos con las comas. Si lo desea, puede seguir con un script sed simple para eliminar los espacios en blanco que aparecen antes de una coma.

Algo como esto podría funcionar ... (mis habilidades sed están muy oxidadas, por lo que es probable que esto necesite trabajo)

sed 's/\s+,/,/' myfile.csv 
Gabe
fuente
Falta el "," en la línea colsep te. También es probable que el headsep off y el tamaño de línea X sean útiles. Edite la respuesta y la aceptaré.
Daniel C. Sobral
55
El comando sed es: cat myfile.csv | sed -e 's / [\ t] * | / | / g; s / | [] * / | / g '> myfile.csv. De todos modos, Oracle realmente apesta.
Stan
2
Y para conseguir un encabezado con los nombres de columna usar set pagesize 1000en lugar de 0. En mi comentario anterior, no se puede redirigir en el mismo archivo: cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv.
Stan
1
Filtré los espacios en blanco y los guiones solían subrayar con grepy trasí grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013
1
@slayernoah, el comando spool puede tomar una ruta de directorio y un nombre de archivo, para que pueda especificar exactamente dónde se colocará el archivo de salida. De lo contrario, dependería de la ubicación donde esté ejecutando el script.
Gabe
35

Uso este comando para scripts que extraen datos para tablas dimensionales (DW). Entonces, uso la siguiente sintaxis:

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

Y funciona. No uso sed para formatear el archivo de salida.

Hallison Batista
fuente
24

Veo un problema similar ...

Necesito poner en cola el archivo CSV de SQLPLUS, pero el resultado tiene 250 columnas.

Lo que hice para evitar el molesto formato de salida 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

el problema es que perderá los nombres de encabezado de columna ...

puedes agregar esto:

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

Sé que es un poco duro, pero funciona para mí ...

Karlos
fuente
¿necesitamos ||también subconsultas ?, no creo que sea necesario para las subconsultas. pero sí, se requiere para la selección primaria.
davidb
¿Para qué sirve el exterior adicional select x? Esto debería funcionar sin él. @davidb, tiene razón en que la concatenación no es necesaria en la subconsulta interna primaria, pero alias todas las columnas como col1, col2 ... etc. Se requiere allí.
Amit Naidu
18

Con las versiones más recientes de las herramientas del cliente, existen múltiples opciones para formatear el resultado de la consulta. El resto es ponerlo en cola en un archivo o guardar la salida como un archivo dependiendo de la herramienta del cliente. Estas son algunas de las formas:

  • SQL * Plus

Usando los comandos SQL * Plus, puede formatear para obtener el resultado deseado. Use SPOOL para poner en cola la salida a un archivo.

Por ejemplo,

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 Version pre 4.1

Alternativamente, puede usar la nueva pista en SQL Developer ./*csv*/

/*csv*/

Por ejemplo, en mi SQL Developer Versión 3.2.20.10 :

ingrese la descripción de la imagen aquí

Ahora podría guardar la salida en un archivo.

  • Desarrollador SQL Versión 4.1

Nuevo en SQL Developer versión 4.1, use lo siguiente al igual que el comando sqlplus y ejecútelo como script. No es necesario la pista en la consulta.

SET SQLFORMAT csv

Ahora podría guardar la salida en un archivo.

Lalit Kumar B
fuente
12

Sé que este es un hilo antiguo, sin embargo, noté que nadie mencionó la opción de subrayado, que puede eliminar los subrayados debajo de los encabezados de las columnas.

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;
Doc
fuente
Buena captura en la opción de subrayado, necesitaba esa.
knockando el
Es bueno si desea un csv con una fila superior que contenga el título / encabezados para cada columna. Ayudaría a cualquiera que quiera ver el archivo csv y descubrir lo que está viendo, etc ...
Doc
10

Es crudo, pero:

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
fuente
7

Puede formatear explícitamente la consulta para producir una cadena delimitada con algo similar a:

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

Y configure las opciones de salida según corresponda. Como opción, la variable COLSEP en SQLPlus le permitirá producir archivos delimitados sin tener que generar explícitamente una cadena con los campos concatenados juntos. Sin embargo, tendrá que poner comillas alrededor de las cadenas en cualquier columna que pueda contener caracteres de coma incrustados.

Preocupado por TunbridgeWells
fuente
4

prefiera usar "set colsep" en el prompt sqlplus en lugar de editar el nombre de col uno por uno. Use sed para editar el archivo de salida.

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

Una vez escribí un pequeño script SQL * Plus que usa dbms_sqly dbms_outputpara crear un csv (en realidad un ssv). Puedes encontrarlo en mi repositorio Githup .

René Nyffenegger
fuente
2

Debe tener en cuenta que los valores de los campos pueden contener comas y caracteres de comillas, por lo que algunas de las respuestas sugeridas no funcionarían, ya que el archivo de salida CSV no sería correcto. Para reemplazar los caracteres de comillas en un campo y reemplazarlos con el carácter de comillas dobles, puede usar la función REEMPLAZAR que proporciona Oracle, para cambiar una comilla simple a comilla doble.

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

O, si desea el carácter de comillas simples para los campos:

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
fuente
El trim()es innecesario.
Amit Naidu
1

Use vi o vim para escribir el sql, use colsep con un control-A (en vi y vim preceden el ctrl-A con un ctrl-v). Asegúrese de establecer el tamaño de línea y el tamaño de página en algo racional y active el trimspool y el recorte.

ponerlo en cola en un archivo. Luego...

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

Esa cosa sed puede convertirse en un guión. El "*" antes y después del ctrl-A exprime todos los espacios inútiles. ¿No es genial que se hayan molestado en habilitar la salida html de sqlplus pero NO en el csv nativo?

Lo hago de esta manera porque maneja comas en los datos. Los convierto en punto y coma.

Charles Stepp
fuente
3
Esto falla la prueba "Debo usar SQLPlus".
Daniel C. Sobral
0

Hay un problema al usar sqlplus para crear archivos csv. Si desea los encabezados de columna solo una vez en la salida y hay miles o millones de filas, no puede establecer un tamaño de página lo suficientemente grande como para no repetir. La solución es comenzar con pagesize = 50 y analizar los encabezados, luego emitir la selección nuevamente con pagesize = 0 para obtener los datos. Ver script bash a continuación:

#!/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
fuente
0

Escribí este script puramente SQLPlus para volcar tablas a CSV en 1994.

Como se señaló en los comentarios del script, alguien en Oracle puso mi script en una nota de Soporte de Oracle, pero sin atribución.

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

El script también crea un archivo de control y un archivo de parámetros para SQL * LOADER

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

    select * from emp
    
    spool off
Satheeshkumar P
fuente
-3

Puede usar la sugerencia csv. Vea el siguiente ejemplo:

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