Como faço o spool para um arquivo formatado em CSV usando o SQLPLUS?
143
Quero extrair algumas consultas para um formato de saída CSV. Infelizmente, não posso usar nenhum cliente SQL sofisticado ou qualquer idioma para fazer isso. Eu devo usar o SQLPLUS.
Por favor, marque como correta a resposta dada pelo @BobC. Falta o comando spool para imprimir o arquivo, mas é a solução mais simples para exportar dados no formato csv.
rlar 17/04
Respostas:
28
Se você estiver usando o 12.2, pode simplesmente dizer
Alguém sabe como desativar o eco, o óbvio "definir eco desativado" não parece funcionar com isso?
Quaternion
Supondo que isso seja porque você está executando um script e gravando em um arquivo, você deve apenas "desativar o termout"
BobC:
155
Você também pode usar o seguinte, embora ele introduza espaços entre os campos.
set colsep ,-- separate columns with a commaset pagesize 0-- No header rowsset trimspool on-- remove trailing blanksset headsep off-- this may or may not be useful...depends on your headings.set linesize X -- X should be the sum of the column widthsset numw X -- X should be the length you want for numbers (avoid scientific notation on IDs)
spool myfile.csvselect table_name, tablespace_name from all_tableswhere owner ='SYS'and tablespace_name isnotnull;
Isso seria muito menos entediante do que digitar todos os campos e concatená-los com vírgulas. Você pode seguir com um script sed simples para remover o espaço em branco que aparece antes de uma vírgula, se desejar.
Algo como isso pode funcionar ... (minhas habilidades de sed são muito enferrujadas, então isso provavelmente precisará de trabalho)
O "," está ausente na linha colsep. Além disso, o headsep off e o tamanho de linha X provavelmente serão úteis. Edite a resposta e eu aceito.
1813 Daniel C. Sobral
5
O comando sed é: cat myfile.csv | sed -e 's / [\ t] * | / | / g; s / | [] * / | / g '> meuarquivo.csv. De qualquer forma, a Oracle é realmente péssima.
Stan
2
E para obter um cabeçalho com os nomes das colunas usar set pagesize 1000, em vez de 0. Na minha comentário anterior, você não pode redirecionar para o mesmo arquivo: cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv.
Stan
1
Eu filtrava os espaços em branco e os traços usados para sublinhar grepe trassim grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013
1
@slayernoah o comando spool pode usar o caminho do diretório e o nome do arquivo, para que você possa especificar exatamente onde o arquivo de saída será colocado. Caso contrário, isso dependeria do local em que você está executando o script.
Gabe
35
Eu uso esse comando para scripts que extrai dados para tabelas dimensionais (DW). Então, eu uso a seguinte sintaxe:
set colsep '|'set echo offset feedback offset linesize 1000set pagesize 0set sqlprompt ''set trimspool onset headsep off
spool output.datselect'|',<table>.*,'|'from<table>where<conditions>
spool off
E funciona. Eu não uso sed para formatar o arquivo de saída.
Preciso colocar em spool o arquivo CSV do SQLPLUS, mas a saída possui 250 colunas.
O que fiz para evitar a irritante formatação de saída SQLPLUS:
set linesize 9999set pagesize 50000
spool myfile.csvselect xfrom(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 xfrom(... here is the "core"select));
spool off
o problema é que você perderá os nomes dos cabeçalhos das colunas ...
você pode adicionar isto:
set heading off
spool myfile.csvselect 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 xfrom(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 xfrom(... here is the "core"select));
spool off
Eu sei que é meio hardcore, mas funciona para mim ...
também precisamos ||de subconsulta ?, acho que não é necessário para as subconsultas. mas sim, é necessário para a seleção primária.
Davidb
Para que serve o exterior extra select x? Isso deve funcionar sem ele. @ Davididb, você está certo de que a concatenação não é necessária na subconsulta interna primária, mas com o alias de todas as colunas como col1, col2 ... etc. é necessário lá.
Amit Naidu
18
Com versões mais recentes das ferramentas do cliente, há várias opções para formatar a saída da consulta. O restante é colocar em spool em um arquivo ou salvar a saída como um arquivo, dependendo da ferramenta do cliente. Aqui estão algumas das maneiras:
SQL * Plus
Usando os comandos SQL * Plus, você pode formatar para obter a saída desejada. Use SPOOL para colocar a saída em spool em um arquivo.
Eu sei que este é um thread antigo, no entanto, notei que ninguém mencionou a opção de sublinhado, que pode remover os sublinhados sob os títulos das colunas.
set pagesize 50000--50k is the max as of 12cset linesize 10000set trimspool on--remove trailing blankspacesset underline off--remove the dashes/underlines under the col headersset colsep ~select*from DW_TMC_PROJECT_VW;
É bom se você quiser um csv com uma linha superior que contenha o título / títulos de cada coluna. Isso ajudaria qualquer um que pode querer ver o arquivo CSV, e descobrir o que eles estão olhando, etc ...
Doc
10
É bruto, mas:
set pagesize 0 linesize 500 trimspool on feedback off echo offselect'"'|| empno ||'","'|| ename ||'","'|| deptno ||'"'as textfrom emp
spool emp.csv/
spool off
Você pode formatar explicitamente a consulta para produzir uma sequência delimitada com algo parecido com:
select'"'||foo||'","'||bar||'"'from tab
E configure as opções de saída conforme apropriado. Como opção, a variável COLSEP no SQLPlus permitirá produzir arquivos delimitados sem a necessidade de gerar explicitamente uma sequência com os campos concatenados juntos. No entanto, você precisará colocar aspas nas seqüências de caracteres em qualquer coluna que possa conter caracteres de vírgula incorporados.
Certa vez, escrevi um pequeno script SQL * Plus que usa dbms_sqle dbms_outputcria um csv (na verdade um ssv). Você pode encontrá-lo no meu repositório githup .
Você deve estar ciente de que os valores dos campos podem conter vírgulas e caracteres de cotação, portanto, algumas das respostas sugeridas não funcionariam, pois o arquivo de saída CSV não estaria correto. Para substituir caracteres de aspas em um campo e substituí-los pelo caractere de aspas duplas, você pode usar a função REPLACE fornecida pelo oracle, para alterar uma aspas simples para aspas duplas.
set echo offset heading offset feedback offset linesize 1024-- or some other value, big enoughset pagesize 50000set verify offset trimspool on
spool output.csv
select trim('"'|| replace(col1,'"','""')||'","'|| replace(col2,'"','""')||'","'|| replace(coln,'"','""')||'"')-- etc. for all the columnsfrom yourtable
/
spool off
Ou, se você desejar o caractere de aspas simples para os campos:
set echo offset heading offset feedback offset linesize 1024-- or some other value, big enoughset pagesize 50000set verify offset trimspool on
spool output.csv
select trim('"'|| replace(col1,'''','''''')||'","'|| replace(col2,'''','''''')||'","'|| replace(coln,'''','''''')||'"')-- etc. for all the columnsfrom yourtable
/
spool off
Use vi ou vim para escrever o sql, use colsep com um controle-A (no vi e vim preceda o ctrl-A com um ctrl-v). Certifique-se de definir o tamanho da linha e o tamanho da página como algo racional e ative o trimspool e o trimout.
coloque em um arquivo em spool. Então...
sed -e 's/,/;/g'-e 's/ *{ctrl-a} */,/g'{spooled file}> output.csv
Essa coisa sed pode ser transformada em um script. O "*" antes e depois do ctrl-A apaga todos os espaços inúteis. Não é ótimo que eles se preocuparam em habilitar a saída html do sqlplus, mas NÃO o csv nativo ?????
Eu faço dessa maneira porque lida com vírgulas nos dados. Eu os transforma em ponto e vírgula.
Há um problema ao usar o sqlplus para criar arquivos csv. Se você quiser os cabeçalhos das colunas apenas uma vez na saída e houver milhares ou milhões de linhas, não poderá definir o tamanho da página suficientemente grande para não repetir. A solução é começar com tamanho da página = 50 e analisar os cabeçalhos e emitir o select novamente com tamanho da página = 0 para obter os dados. Veja o script bash abaixo:
#!/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/nullset 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/nullset 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
}
Respostas:
Se você estiver usando o 12.2, pode simplesmente dizer
fonte
Você também pode usar o seguinte, embora ele introduza espaços entre os campos.
A saída será como:
Isso seria muito menos entediante do que digitar todos os campos e concatená-los com vírgulas. Você pode seguir com um script sed simples para remover o espaço em branco que aparece antes de uma vírgula, se desejar.
Algo como isso pode funcionar ... (minhas habilidades de sed são muito enferrujadas, então isso provavelmente precisará de trabalho)
fonte
set pagesize 1000
, em vez de 0. Na minha comentário anterior, você não pode redirecionar para o mesmo arquivo:cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv
.grep
etr
assimgrep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.Eu uso esse comando para scripts que extrai dados para tabelas dimensionais (DW). Então, eu uso a seguinte sintaxe:
E funciona. Eu não uso sed para formatar o arquivo de saída.
fonte
Vejo um problema semelhante ...
Preciso colocar em spool o arquivo CSV do SQLPLUS, mas a saída possui 250 colunas.
O que fiz para evitar a irritante formatação de saída SQLPLUS:
o problema é que você perderá os nomes dos cabeçalhos das colunas ...
você pode adicionar isto:
Eu sei que é meio hardcore, mas funciona para mim ...
fonte
||
de subconsulta ?, acho que não é necessário para as subconsultas. mas sim, é necessário para a seleção primária.select x
? Isso deve funcionar sem ele. @ Davididb, você está certo de que a concatenação não é necessária na subconsulta interna primária, mas com o alias de todas as colunas como col1, col2 ... etc. é necessário lá.Com versões mais recentes das ferramentas do cliente, há várias opções para formatar a saída da consulta. O restante é colocar em spool em um arquivo ou salvar a saída como um arquivo, dependendo da ferramenta do cliente. Aqui estão algumas das maneiras:
Usando os comandos SQL * Plus, você pode formatar para obter a saída desejada. Use SPOOL para colocar a saída em spool em um arquivo.
Por exemplo,
Como alternativa, você pode usar a nova dica no SQL Developer .
/*csv*/
Por exemplo, no meu SQL Developer Versão 3.2.20.10 :
Agora você pode salvar a saída em um arquivo.
Novo no SQL Developer versão 4.1, use o seguinte como o comando sqlplus e execute como script. Não há necessidade da dica na consulta.
Agora você pode salvar a saída em um arquivo.
fonte
Eu sei que este é um thread antigo, no entanto, notei que ninguém mencionou a opção de sublinhado, que pode remover os sublinhados sob os títulos das colunas.
fonte
É bruto, mas:
fonte
Você pode formatar explicitamente a consulta para produzir uma sequência delimitada com algo parecido com:
E configure as opções de saída conforme apropriado. Como opção, a variável COLSEP no SQLPlus permitirá produzir arquivos delimitados sem a necessidade de gerar explicitamente uma sequência com os campos concatenados juntos. No entanto, você precisará colocar aspas nas seqüências de caracteres em qualquer coluna que possa conter caracteres de vírgula incorporados.
fonte
prefira usar "set colsep" no prompt do sqlplus em vez de editar o nome da coluna, um por um. Use sed para editar o arquivo de saída.
fonte
Certa vez, escrevi um pequeno script SQL * Plus que usa
dbms_sql
edbms_output
cria um csv (na verdade um ssv). Você pode encontrá-lo no meu repositório githup .fonte
Você deve estar ciente de que os valores dos campos podem conter vírgulas e caracteres de cotação, portanto, algumas das respostas sugeridas não funcionariam, pois o arquivo de saída CSV não estaria correto. Para substituir caracteres de aspas em um campo e substituí-los pelo caractere de aspas duplas, você pode usar a função REPLACE fornecida pelo oracle, para alterar uma aspas simples para aspas duplas.
Ou, se você desejar o caractere de aspas simples para os campos:
fonte
trim()
é desnecessário.Use vi ou vim para escrever o sql, use colsep com um controle-A (no vi e vim preceda o ctrl-A com um ctrl-v). Certifique-se de definir o tamanho da linha e o tamanho da página como algo racional e ative o trimspool e o trimout.
coloque em um arquivo em spool. Então...
Essa coisa sed pode ser transformada em um script. O "*" antes e depois do ctrl-A apaga todos os espaços inúteis. Não é ótimo que eles se preocuparam em habilitar a saída html do sqlplus, mas NÃO o csv nativo ?????
Eu faço dessa maneira porque lida com vírgulas nos dados. Eu os transforma em ponto e vírgula.
fonte
Há um problema ao usar o sqlplus para criar arquivos csv. Se você quiser os cabeçalhos das colunas apenas uma vez na saída e houver milhares ou milhões de linhas, não poderá definir o tamanho da página suficientemente grande para não repetir. A solução é começar com tamanho da página = 50 e analisar os cabeçalhos e emitir o select novamente com tamanho da página = 0 para obter os dados. Veja o script bash abaixo:
fonte
Eu escrevi esse script puramente SQLPlus para despejar tabelas no CSV em 1994.
Conforme observado nos comentários do script, alguém na Oracle colocou meu script em uma nota de suporte Oracle, mas sem atribuição.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
O script também cria um arquivo de controle e um arquivo de parâmetro para SQL * LOADER
fonte
fonte
Você pode usar a dica csv. Veja o seguinte exemplo:
fonte