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.
Como eu faço isso?
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.
Como eu faço isso?
Respostas:
Se você estiver usando o 12.2, pode simplesmente dizer
set markup csv on
spool myfile.csv
Você também pode usar o seguinte, embora ele introduza espaços entre os 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;
A saída será como:
TABLE_PRIVILEGE_MAP ,SYSTEM
SYSTEM_PRIVILEGE_MAP ,SYSTEM
STMT_AUDIT_OPTION_MAP ,SYSTEM
DUAL ,SYSTEM
...
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)
sed 's/\s+,/,/' myfile.csv
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
e tr
assim grep -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:
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
E funciona. Eu não uso sed para formatar o arquivo de saída.
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:
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
o problema é que você perderá os nomes dos cabeçalhos das colunas ...
você pode adicionar isto:
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
Eu sei que é meio hardcore, mas funciona para mim ...
||
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,
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>
Como alternativa, você pode usar a nova dica no SQL Developer ./*csv*/
/*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.
SET SQLFORMAT csv
Agora você pode salvar a saída 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 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;
É bruto, mas:
set pagesize 0 linesize 500 trimspool on feedback off echo off
select '"' || empno || '","' || ename || '","' || deptno || '"' as text
from 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_sql
e dbms_output
cria 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 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
Ou, se você desejar o caractere de aspas simples para os 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
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...
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/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
}
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
spool D:\test.txt
select * from emp
spool off
Você pode usar a dica csv. Veja o seguinte exemplo:
select /*csv*/ table_name, tablespace_name
from all_tables
where owner = 'SYS'
and tablespace_name is not null;