Je souhaite extraire des requêtes dans un format de sortie CSV. Malheureusement, je ne peux utiliser aucun client SQL sophistiqué ni aucun langage pour le faire. Je dois utiliser SQLPLUS.
Comment fait-on ça?
Vous pouvez également utiliser ce qui suit, bien qu'il 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. Si vous le souhaitez, vous pouvez utiliser un script sed simple pour supprimer les espaces avant les virgules.
Quelque chose comme cela pourrait fonctionner ... (mes compétences sed sont très rouillées, donc cela nécessitera probablement du travail)
sed 's/\s+,/,/' myfile.csv
J'utilise cette commande pour les scripts qui extraient des données pour des tables dimensionnelles (DW). Donc, j'utilise 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 fonctionne. Je n'utilise pas sed pour formater le fichier de sortie.
Je vois un problème similaire ...
J'ai besoin de spouler le fichier CSV à partir de SQLPLUS, mais la sortie comporte 250 colonnes.
Ce que j'ai fait pour éviter le formatage de sortie SQLPLUS ennuyeux:
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 allez perdre les noms d'en-tête de colonne ...
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 ...
Avec les nouvelles versions des outils clients, il existe plusieurs options pour formater la sortie de la requête. Le reste consiste à le spouler dans un fichier ou à enregistrer la sortie sous forme de fichier en fonction de l'outil client. Voici quelques exemples:
En utilisant les commandes SQL * Plus, vous pouvez formater pour obtenir le résultat souhaité. Utilisez SPOOL pour spooler la sortie dans un fichier.
Par exemple,
_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>
_
Vous pouvez également utiliser le nouveau /*csv*/
indice dans SQL Developer.
_/*csv*/
_
Par exemple, dans mon SQL Developer Version 3.2.20.1:
Vous pouvez maintenant enregistrer la sortie dans un fichier.
Nouveau dans SQL Developer version 4.1, utilisez les éléments suivants, tout comme la commande sqlplus, et exécutez-les en tant que script. Pas besoin de l'allusion dans la requête.
_SET SQLFORMAT csv
_
Vous pouvez maintenant enregistrer la sortie dans un fichier.
Si vous utilisez 12.2, vous pouvez simplement dire
set markup csv on
Je sais que c’est un vieux sujet, mais j’ai remarqué que personne n’a mentionné l’option soulignement, qui permet de supprimer les soulignements sous les en-têtes de colonne.
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;
C'est brutal, 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
Vous pouvez explicitement formater la requête pour produire une chaîne délimitée avec quelque chose du type:
select '"'||foo||'","'||bar||'"'
from tab
Et configurez les options de sortie selon vos besoins. En option, la variable COLSEP sur 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. Toutefois, vous devrez mettre des guillemets autour des chaînes de toutes les colonnes pouvant contenir des caractères de virgule incorporés.
préférez utiliser "set colsep" dans sqlplus Prompt au lieu d’éditer un nom de col un par un. Utilisez sed pour éditer le fichier de sortie.
set colsep '","' -- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
J'ai déjà écrit un petit script SQL * Plus qui utilise dbms_sql
et dbms_output
pour créer un csv (en réalité un ssv). Vous pouvez le trouver sur mon dépôt githup .
Utilisez vi ou vim pour écrire le sql, utilisez colsep avec un control-A (dans vi et vim précèdent ctrl-A avec un ctrl-v). Assurez-vous de définir une taille de ligne et une taille de page rationnelles et d’activer Trimspool et Trimout.
spouler dans un fichier. Ensuite...
sed -e 's/,/;/g' -e 's/ *{ctrl-a} */,/g' {spooled file} > output.csv
Cette chose sed peut être transformée en script. Le "*" avant et après le Ctrl-A supprime tous les espaces inutiles. N’est-ce pas formidable qu’ils aient pris la peine d’activer la sortie HTML de sqlplus mais PAS de CSV natif ?????
Je le fais de cette façon car il gère les virgules dans les données. Je les transforme en points-virgules.
Sachez que les valeurs des champs peuvent contenir des virgules et des caractères de citation. Par conséquent, certaines des réponses suggérées ne fonctionneraient pas car le fichier de sortie CSV ne serait pas correct. Pour remplacer les guillemets dans un champ et le remplacer par le guillemet double, vous pouvez utiliser la fonction REPLACE fournie par Oracle pour modifier un guillemet simple.
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, si vous voulez le caractère guillemet simple pour les champs:
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
Il y a un problème d'utilisation de sqlplus pour créer des fichiers csv. Si vous souhaitez que les en-têtes de colonne ne soient affichés qu'une seule fois dans la sortie et qu'il existe des milliers, voire des millions, de lignes, vous ne pouvez pas définir une taille de page suffisamment grande pour ne pas obtenir de répétition. La solution consiste à commencer par pagesize = 50 et à analyser les en-têtes, puis à relancer select avec pagesize = 0 pour récupérer les données. Voir le script bash ci-dessous:
#!/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
}
J'ai écrit ce script purement SQLPlus pour dump des tables au format CSV en 1994.
Comme indiqué dans les commentaires de script, quelqu'un chez Oracle a placé mon script dans une note de support Oracle, mais sans attribution.
https://github.com/jkstill/Oracle-script-lib/blob/master/sql/dump.sql
Le script crée également un fichier de contrôle et un fichier de paramètres pour SQL * LOADER.