165 votes

Comment faire un spool vers un fichier au format CSV en utilisant SQLPLUS ?

Je veux extraire certaines requêtes vers un format de sortie CSV. Malheureusement, je ne peux pas utiliser un client SQL fantaisiste ou un langage quelconque pour le faire. Je dois utiliser SQLPLUS.

Comment dois-je m'y prendre ?

160voto

Gabe Points 826

Vous pouvez également utiliser la méthode suivante, bien qu'elle introduise des espaces entre les champs.

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 sortie sera comme :

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

Ce serait beaucoup moins fastidieux que de taper tous les champs et de les concaténer avec les virgules. Vous pourriez poursuivre avec un simple sed script pour supprimer les espaces blancs qui apparaissent avant une virgule, si vous le souhaitez.

Quelque chose comme ceci pourrait fonctionner...(mes compétences en matière de séduction sont très rouillées, donc il faudra probablement y travailler)

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

1 votes

Le "," est manquant dans la ligne de colsep. De même, headsep off et linesize X sont susceptibles d'être utiles. Editez la réponse et je l'accepterai.

0 votes

Merci pour les commentaires, Daniel. L'option "set linesize" est certainement utile, et je l'ai utilisée dans le passé pour ce genre de choses.

6 votes

La commande sed est : cat monfichier.csv | sed -e 's/[ \t ]*|/|/g ; s/|[ ]*/|/g' > monfichier.csv. Quoi qu'il en soit, Oracle est vraiment nul.

38voto

Hallison Batista Points 141

J'utilise cette commande pour les scripts qui extraient des données pour les tables dimensionnelles (DW). J'utilise donc la syntaxe suivante :

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

Et ça marche. Je n'utilise pas sed pour formater le fichier de sortie.

24voto

Karlos Points 91

Je vois un problème similaire...

J'ai besoin de spooler un fichier CSV à partir de SQLPLUS, mais la sortie a 250 colonnes.

Ce que j'ai fait pour éviter le formatage ennuyeux de la sortie de 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

le problème est que vous perdrez les noms des en-têtes de colonnes...

vous pouvez ajouter ceci :

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

Je sais que c'est un peu hardcore, mais ça marche pour moi...

0 votes

Avons-nous besoin || pour les sous-requêtes aussi ? je ne pense pas que ce soit nécessaire pour les sous-requêtes. mais oui c'est nécessaire pour la sélection primaire.

0 votes

Quel est l'extra extérieur select x pour ? Cela devrait fonctionner sans cela. @davidb, vous avez raison de dire que la concaténation n'est pas nécessaire dans la sous-requête primaire interne, mais l'alias de toutes les colonnes comme col1, col2...etc. est nécessaire.

10voto

Tony Andrews Points 67363

C'est grossier, mais :

set pagesize 0 linesize 500 trimspool on feedback off echo off

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

spool emp.csv
/
spool off

7voto

Vous pouvez formater explicitement la requête pour produire une chaîne de caractères délimitée avec quelque chose du genre :

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

Et configurez les options de sortie comme il convient. En option, la variable COLSEP de SQLPlus vous permettra de produire des fichiers délimités sans avoir à générer explicitement une chaîne avec les champs concaténés ensemble. Cependant, vous devrez mettre des guillemets autour des chaînes sur toutes les colonnes qui pourraient contenir des caractères de virgule incorporés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X