Как выполнить буферизацию в файл в формате CSV с помощью SQLPLUS?
145
Я хочу извлечь некоторые запросы в выходной формат CSV. К сожалению, я не могу использовать какой-либо модный клиент SQL или какой-либо язык для этого. Я должен использовать SQLPLUS.
Пожалуйста, отметьте как правильный ответ @BobC. Отсутствует команда спула для печати файла, но это простейшее решение для экспорта данных в формате csv.
rlar
Ответы:
32
Если вы используете 12.2, вы можете просто сказать
Кто-нибудь знает, как отключить эхо, очевидное "установить эхо выключено" вроде с этим не работает?
Quaternion
Предполагая, что это связано с тем, что вы выполняете сценарий и записываете в файл, вам следует просто «отключить termout»
BobC
157
Вы также можете использовать следующее, хотя оно вводит пробелы между полями.
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.csv
select table_name, tablespace_name
from all_tables
where owner = 'SYS'and tablespace_name isnotnull;
Это было бы намного менее утомительно, чем вводить все поля и объединять их запятыми. Вы можете продолжить с помощью простого сценария sed, чтобы удалить пробелы, которые появляются перед запятой, если хотите.
Что-то вроде этого может сработать ... (мои навыки работы с sed очень ржавые, так что это, вероятно, потребует работы)
В строке te colsep отсутствует ",". Также, вероятно, будут полезны хэдсайз и линейный размер X. Отредактируйте ответ, и я его приму.
Дэниел С. Собрал,
5
Команда sed: cat myfile.csv | sed -e 's / [\ t] * | / | / г; s / | [] * / | / g '> myfile.csv. В любом случае, Oracle действительно отстой.
Stan
2
А чтобы получить заголовок с именами столбцов использовать set pagesize 1000вместо 0. В моем предыдущем комментарии, вы не можете перенаправить в тот же файл: cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv.
Stan
1
Я отфильтрован пробела и тир , используемый для подчеркивания с grepи trтак grep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv.
ixe013
1
@slayernoah команда spool может принимать путь к каталогу и имя файла, так что вы можете точно указать, где будет размещен выходной файл. В противном случае это будет зависеть от места, где вы выполняете сценарий.
Гейб
35
Я использую эту команду для скриптов, которые извлекают данные для размерных таблиц (DW). Итак, я использую следующий синтаксис:
set colsep '|'set echo offset feedback offset linesize 1000set pagesize 0set sqlprompt ''set trimspool onset headsep off
spool output.dat
select'|', <table>.*, '|'from <table>
where <conditions>
spool off
И работает. Я не использую sed для форматирования выходного файла.
Мне нужно спутировать CSV-файл из SQLPLUS, но на выходе 250 столбцов.
Что я сделал, чтобы не раздражать форматирование вывода SQLPLUS:
set linesize 9999set 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
проблема в том, что вы потеряете имена заголовков столбцов ...
вы можете добавить это:
setheadingoff
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
Я знаю, что это хардкорно, но у меня это работает ...
нужен ли нам и ||подзапрос? Я не думаю, что он нужен для подзапросов. но да, это требуется для первичного выбора.
DavidB
Для чего нужен дополнительный внешний select x? Это должно работать и без него. @davidb, вы правы, что в основном внутреннем подзапросе конкатенация не требуется, а для всех столбцов используется псевдоним col1, col2 ... и т. д. там требуется.
Амит Найду
18
В более новых версиях клиентских инструментов есть несколько вариантов форматирования вывода запроса. Остальное - поместить его в файл или сохранить вывод как файл, в зависимости от клиентского инструмента. Вот несколько способов:
SQL * Plus
Используя команды SQL * Plus, вы можете отформатировать, чтобы получить желаемый результат. Используйте SPOOL для буферизации вывода в файл.
В качестве альтернативы вы можете использовать новую подсказку в SQL Developer ./*csv*/
/*csv*/
Например, в моей версии SQL Developer 3.2.20.10 :
Теперь вы можете сохранить результат в файл.
SQL Developer версии 4.1
Новое в SQL Developer версии 4.1: используйте следующую команду точно так же, как команду sqlplus, и запускайте как сценарий. Намек в запросе не нужен.
Я знаю, что это старый поток, однако я заметил, что никто не упомянул опцию подчеркивания, которая может удалить подчеркивание под заголовками столбцов.
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;
Это хорошо, если вам нужен csv с верхней строкой, содержащей заголовок / заголовки для каждого столбца. Это поможет любому, кто захочет просмотреть csv-файл, выяснить, на что он смотрит, и т. Д.
Док
10
Это грубо, но:
set pagesize 0 linesize 500 trimspool on feedback off echo offselect'"' || empno || '","' || ename || '","' || deptno || '"'astextfrom emp
spool emp.csv
/
spool off
Вы можете явно отформатировать запрос, чтобы получить строку с разделителями, содержащую что-то вроде:
select'"'||foo||'","'||bar||'"'from tab
И настройте параметры вывода соответствующим образом. Как вариант, переменная COLSEP в SQLPlus позволит вам создавать файлы с разделителями без необходимости явно генерировать строку с полями, объединенными вместе. Однако вам придется заключать в кавычки строки в любых столбцах, которые могут содержать встроенные символы запятой.
предпочитаю использовать "set colsep" в приглашении sqlplus вместо того, чтобы редактировать имя столбца по одному. Используйте sed для редактирования выходного файла.
set colsep '","'-- separate columns with a comma
sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
Однажды я написал небольшой скрипт SQL * Plus, который использует dbms_sqlи dbms_outputдля создания csv (на самом деле ssv). Вы можете найти его в моем репозитории на githup .
Вы должны знать, что значения полей могут содержать запятые и кавычки, поэтому некоторые из предложенных ответов не будут работать, так как выходной файл CSV будет неправильным. Чтобы заменить символы кавычек в поле и заменить их символом двойной кавычки, вы можете использовать функцию REPLACE, предоставляемую oracle, для изменения одинарной кавычки на двойные кавычки.
set echo offsetheadingoffset feedback offset linesize 1024-- or some other value, big enoughset pagesize 50000setverifyoffset trimspool on
spool output.csv
selecttrim(
'"' || replace(col1, '"', '""') ||
'","' || replace(col2, '"', '""') ||
'","' || replace(coln, '"', '""') || '"' ) -- etc. for all the columnsfrom yourtable
/
spool off
Или, если вам нужен символ одинарной кавычки для полей:
set echo offsetheadingoffset feedback offset linesize 1024-- or some other value, big enoughset pagesize 50000setverifyoffset trimspool on
spool output.csv
selecttrim(
'"' || replace(col1, '''', '''''') ||
'","' || replace(col2, '''', '''''') ||
'","' || replace(coln, '''', '''''') || '"' ) -- etc. for all the columnsfrom yourtable
/
spool off
Используйте vi или vim для записи sql, используйте colsep с Control-A (в vi и vim перед ctrl-A ставите ctrl-v). Обязательно установите для размера линии и страницы что-то рациональное и включите триммер и обрезку.
Эту sed-вещь можно превратить в скрипт. Знак "*" до и после ctrl-A вытесняет все бесполезные пробелы. Разве это не здорово, что они удосужились включить вывод html из sqlplus, но НЕ родной csv ?????
Я делаю это так, потому что он обрабатывает запятые в данных. Я превращаю их в точки с запятой.
Это не соответствует тесту «Я должен использовать SQLPlus».
Дэниел С. Собрал
0
Возникла проблема с использованием sqlplus для создания файлов CSV. Если вы хотите, чтобы заголовки столбцов выводились только один раз и были тысячи или миллионы строк, вы не можете установить достаточно большой размер страницы, чтобы не повторяться. Решение состоит в том, чтобы начать с pagesize = 50 и проанализировать заголовки, а затем снова выполнить выбор с помощью pagesize = 0, чтобы получить данные. Смотрите сценарий bash ниже:
#!/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;
setverifyoff;
set feedback off;
setlong99999;
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} whererownum < 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;
setverifyoff;
set feedback off;
setlong99999;
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
}
Ответы:
Если вы используете 12.2, вы можете просто сказать
set markup csv on spool myfile.csv
источник
Вы также можете использовать следующее, хотя оно вводит пробелы между полями.
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;
Результат будет таким:
Это было бы намного менее утомительно, чем вводить все поля и объединять их запятыми. Вы можете продолжить с помощью простого сценария sed, чтобы удалить пробелы, которые появляются перед запятой, если хотите.
Что-то вроде этого может сработать ... (мои навыки работы с sed очень ржавые, так что это, вероятно, потребует работы)
источник
set pagesize 1000
вместо 0. В моем предыдущем комментарии, вы не можете перенаправить в тот же файл:cat myfile.csv | sed -e 's/[ \t]*|/|/g ; s/|[ ]*/|/g' > my_other_file.csv
.grep
иtr
такgrep -v -- ----- myfile.csv | tr -d [:blank:] > myfile.csv
.Я использую эту команду для скриптов, которые извлекают данные для размерных таблиц (DW). Итак, я использую следующий синтаксис:
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
И работает. Я не использую sed для форматирования выходного файла.
источник
Вижу похожую проблему ...
Мне нужно спутировать CSV-файл из SQLPLUS, но на выходе 250 столбцов.
Что я сделал, чтобы не раздражать форматирование вывода 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
проблема в том, что вы потеряете имена заголовков столбцов ...
вы можете добавить это:
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
Я знаю, что это хардкорно, но у меня это работает ...
источник
||
подзапрос? Я не думаю, что он нужен для подзапросов. но да, это требуется для первичного выбора.select x
? Это должно работать и без него. @davidb, вы правы, что в основном внутреннем подзапросе конкатенация не требуется, а для всех столбцов используется псевдоним col1, col2 ... и т. д. там требуется.В более новых версиях клиентских инструментов есть несколько вариантов форматирования вывода запроса. Остальное - поместить его в файл или сохранить вывод как файл, в зависимости от клиентского инструмента. Вот несколько способов:
Используя команды SQL * Plus, вы можете отформатировать, чтобы получить желаемый результат. Используйте SPOOL для буферизации вывода в файл.
Например,
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 .
/*csv*/
/*csv*/
Например, в моей версии SQL Developer 3.2.20.10 :
Теперь вы можете сохранить результат в файл.
Новое в SQL Developer версии 4.1: используйте следующую команду точно так же, как команду sqlplus, и запускайте как сценарий. Намек в запросе не нужен.
SET SQLFORMAT csv
Теперь вы можете сохранить результат в файл.
источник
Я знаю, что это старый поток, однако я заметил, что никто не упомянул опцию подчеркивания, которая может удалить подчеркивание под заголовками столбцов.
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;
источник
Это грубо, но:
set pagesize 0 linesize 500 trimspool on feedback off echo off select '"' || empno || '","' || ename || '","' || deptno || '"' as text from emp spool emp.csv / spool off
источник
Вы можете явно отформатировать запрос, чтобы получить строку с разделителями, содержащую что-то вроде:
select '"'||foo||'","'||bar||'"' from tab
И настройте параметры вывода соответствующим образом. Как вариант, переменная COLSEP в SQLPlus позволит вам создавать файлы с разделителями без необходимости явно генерировать строку с полями, объединенными вместе. Однако вам придется заключать в кавычки строки в любых столбцах, которые могут содержать встроенные символы запятой.
источник
предпочитаю использовать "set colsep" в приглашении sqlplus вместо того, чтобы редактировать имя столбца по одному. Используйте sed для редактирования выходного файла.
set colsep '","' -- separate columns with a comma sed 's/^/"/;s/$/"/;s/\s *"/"/g;s/"\s */"/g' $outfile > $outfile.csv
источник
Однажды я написал небольшой скрипт SQL * Plus, который использует
dbms_sql
иdbms_output
для создания csv (на самом деле ssv). Вы можете найти его в моем репозитории на githup .источник
Вы должны знать, что значения полей могут содержать запятые и кавычки, поэтому некоторые из предложенных ответов не будут работать, так как выходной файл CSV будет неправильным. Чтобы заменить символы кавычек в поле и заменить их символом двойной кавычки, вы можете использовать функцию REPLACE, предоставляемую oracle, для изменения одинарной кавычки на двойные кавычки.
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
Или, если вам нужен символ одинарной кавычки для полей:
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()
не нужно.Используйте vi или vim для записи sql, используйте colsep с Control-A (в vi и vim перед ctrl-A ставите ctrl-v). Обязательно установите для размера линии и страницы что-то рациональное и включите триммер и обрезку.
спустить его в файл. Затем...
Эту sed-вещь можно превратить в скрипт. Знак "*" до и после ctrl-A вытесняет все бесполезные пробелы. Разве это не здорово, что они удосужились включить вывод html из sqlplus, но НЕ родной csv ?????
Я делаю это так, потому что он обрабатывает запятые в данных. Я превращаю их в точки с запятой.
источник
Возникла проблема с использованием sqlplus для создания файлов CSV. Если вы хотите, чтобы заголовки столбцов выводились только один раз и были тысячи или миллионы строк, вы не можете установить достаточно большой размер страницы, чтобы не повторяться. Решение состоит в том, чтобы начать с pagesize = 50 и проанализировать заголовки, а затем снова выполнить выбор с помощью pagesize = 0, чтобы получить данные. Смотрите сценарий bash ниже:
#!/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 }
источник
Я написал этот чисто SQLPlus-скрипт для дампа таблиц в CSV в 1994 году.
Как отмечено в комментариях к сценарию, кто-то в Oracle поместил мой сценарий в заметку службы поддержки Oracle, но без указания авторства.
https://github.com/jkstill/oracle-script-lib/blob/master/sql/dump.sql
Сценарий также создает управляющий файл и файл параметров для SQL * LOADER.
источник
spool D:\test.txt select * from emp spool off
источник
Вы можете использовать подсказку csv. См. Следующий пример:
select /*csv*/ table_name, tablespace_name from all_tables where owner = 'SYS' and tablespace_name is not null;
источник