Есть ли простой способ запустить запрос MySQL из командной строки Linux и вывести результаты в CSV формат?

Вот что я сейчас делаю:

mysql -u uid -ppwd -D dbname << EOQ | sed -e 's/        /,/g' | tee list.csv
select id, concat("\"",name,"\"") as name
from students
EOQ

Это становится беспорядочным, когда есть много столбцов, которые нужно окружить кавычками, или если в результатах есть кавычки, которые нужно экранировать.

1337
MCS 10 Дек 2008 в 18:59
1
Вы можете использовать REPLACE() в вашем запросе, чтобы кавычки были экранированы.
 – 
dsm
10 Дек 2008 в 19:08
Посмотрите мой ответ в [this stackoverflow] [1] [1]: stackoverflow.com/questions/12242772/…
 – 
biniam
1 Апр 2015 в 19:14
 – 
Somnath Muluk
4 Дек 2015 в 12:45
4
Принятый ответ на этот вопрос о stackoverflow, вероятно, является лучшим способом: stackoverflow.com/questions/ 3760631 / mysql-delimiter-question
 – 
Samuel Åslund
22 Янв 2016 в 19:28
Я написал запрос функции на трекере ошибок MariaDB (jira.mariadb.org/browse/MDEV-12879) Вы можете проголосовать за него.
 – 
Jared Beck
23 Май 2017 в 21:27

30 ответов

Лучший ответ

Из http : //www.tech-recipes.com/rx/1475/save-mysql-query-results-into-a-text-or-csv-file/

SELECT order_id,product_name,qty
FROM orders
WHERE foo = 'bar'
INTO OUTFILE '/var/lib/mysql-files/orders.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';

Примечание. Этот синтаксис, возможно, потребуется изменить на

SELECT order_id,product_name,qty
INTO OUTFILE '/var/lib/mysql-files/orders.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM orders
WHERE foo = 'bar';

В более поздних версиях MySQL.

При использовании этой команды имена столбцов не будут экспортированы.

Также обратите внимание, что /var/lib/mysql-files/orders.csv будет на сервере , на котором работает MySQL. Пользователь, под которым запущен процесс MySQL, должен иметь права на запись в выбранный каталог, иначе команда завершится ошибкой.

Если вы хотите записать вывод на локальную машину с удаленного сервера (особенно с размещенной или виртуализированной машины, такой как Heroku или Amazon RDS), это решение не подходит.

1888
Paul Tomblin 29 Апр 2021 в 22:52
Возможно, вам понадобится root. «Файл создается на хосте сервера, поэтому для использования этого синтаксиса у вас должна быть привилегия FILE». - dev.mysql.com/doc/refman/8.0/en /select-into.html
 – 
Curtis Yallop
24 Июн 2021 в 00:10
$ mysql your_database --password=foo < my_requests.sql > out.csv

Это разделено табуляцией. Подключите его вот так, чтобы получить настоящий CSV (спасибо @therefromhere):

... .sql | sed 's/\t/,/g' > out.csv
510
brent.payne 17 Окт 2012 в 21:05
32
Он разделен табуляцией, а не запятой.
 – 
Flimm
30 Авг 2011 в 19:13
14
@Flimm, при условии, что у вас нет встроенных запятых / вкладок в полях, вы можете преобразовать его, передав результат в | sed 's/\t/,/g'
 – 
John Carter
10 Ноя 2011 в 08:42
119
Sed 'fix' не компенсирует запятые, которые могут появиться в любых выбранных данных, и будет искажать ваши столбцы, выводимые соответствующим образом
 – 
Joey T
11 Дек 2012 в 05:17

mysql --batch, -B

Распечатайте результаты, используя табуляцию в качестве разделителя столбцов, с каждой строкой на новой строке. С этой опцией mysql не использует файл истории. Пакетный режим приводит к нетабличному формату вывода и экранированию специальных символов. Экранирование можно отключить, используя необработанный режим; см. описание параметра --raw.

Это даст вам файл, разделенный табуляцией. Поскольку запятые (или строки, содержащие запятую) не экранируются, изменить разделитель на запятую непросто.

220
serbaut 30 Сен 2009 в 14:51

Вот довольно грубый способ сделать это. Нашел где-то, не могу взять кредит

mysql --user=wibble --password wobble -B -e "select * from vehicle_categories;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > vehicle_categories.csv

Работает неплохо. Еще раз, хотя регулярное выражение доказывает только запись.


Объяснение Regex:

  • s /// означает замену того, что находится между первым //, на то, что находится между вторым //
  • "g" в конце - это модификатор, который означает "весь экземпляр, а не только первый"
  • ^ (в данном контексте) означает начало строки
  • $ (в данном контексте) означает конец строки

Итак, складывая все вместе:

s/'/\'/          replace ' with \'
s/\t/\",\"/g     replace all \t (tab) with ","
s/^/\"/          at the beginning of the line place a "
s/$/\"/          at the end of the line place a "
s/\n//g          replace all \n (newline) with nothing
162
Jeremy Logan 3 Май 2012 в 21:13

Только для Unix / Cygwin, пропустите его через 'tr':

mysql <database> -e "<query here>" | tr '\t' ',' > data.csv

Примечание: при этом не обрабатываются ни встроенные запятые, ни встроенные вкладки.

103
Peter Mortensen 2 Ноя 2015 в 15:09

Это меня пару раз спасало. Быстро и работает!

--batch Печатать результаты, используя вкладку в качестве разделителя столбцов, с каждой строкой на новая строка.

--raw отключает экранирование символа (\ n, \ t, \ 0 и \)

Примере:

mysql -udemo_user -p -h127.0.0.1 --port=3306 \
   --default-character-set=utf8mb4 --database=demo_database \
   --batch --raw < /tmp/demo_sql_query.sql > /tmp/demo_csv_export.tsv

Для полноты вы можете преобразовать в CSV (но будьте осторожны , потому что вкладки могут находиться внутри значений полей - например, текстовые поля)

tr '\t' ',' < file.tsv > file.csv

64
hrvoj3e 16 Апр 2019 в 13:31

Решение OUTFILE, данное Полом Томблином, заставляет файл быть записанным на самом сервере MySQL, поэтому это будет работать, только если у вас есть FILE, а также доступ для входа в систему или другие средства для получения файла из этого ящика.

Если у вас нет такого доступа и вывод с разделителями табуляции является разумной заменой CSV (например, если вашей конечной целью является импорт в Excel), тогда решение Сербаута (с использованием mysql --batch и, возможно, --raw) - это то, что нужно.

41
Leland Woodbury 22 Июн 2010 в 17:48

MySQL Workbench может экспортировать наборы записей в CSV и, похоже, очень хорошо обрабатывает запятые в полях. CSV открывается в OpenOffice нормально.

40
David Oliver 28 Авг 2018 в 18:10
3
Спасибо большое, Дэвид. Потратив 3 часа на то, чтобы новые строки выводились правильно для HTML-содержимого в данных, я использовал MySQL Workbench и через 2 минуты у меня был готов мой CSV-файл.
 – 
mr-euro
11 Июл 2012 в 21:02
Я только что обнаружил, что его можно сохранять и в формате XML, и это здорово. Я надеюсь перейти от одного приложения к другому, используя XSLT для преобразования этого XML в файл CSV, подходящий для импорта в целевое приложение.
 – 
David Oliver
6 Авг 2012 в 01:27
Инструментальная среда mysql - лучший вариант для функции импорта и экспорта.
 – 
cijagani
5 Авг 2015 в 06:20
Что ж, но каждый раз, когда рабочая среда ограничивает количество выбранных записей до 1000, и когда дело доходит до гораздо большего количества записей, она работает не так хорошо, то же условие для импорта часто блокируется, если я пытаюсь импортировать относительно большой файл csv в База данных mysql с помощью верстака.
 – 
LancelotHolmes
29 Окт 2016 в 09:42
1
Я только что успешно экспортировал более полумиллиона строк с помощью mysql workbench, поэтому большие файлы не кажутся проблемой. Вам просто нужно убедиться, что вы удалили ограничение выбора перед запуском вашего запроса, и вам также может потребоваться увеличить следующие значения в вашем файле my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
 – 
Vincent
22 Апр 2018 в 18:47

Как насчет:

mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv
33
dennis 13 Май 2013 в 15:36
2
Мне это очень нравится. Он намного чище, и мне нравится использовать awk. Однако я бы, наверное, пошел так: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
 – 
Josh
11 Апр 2012 в 04:00
8
Это не подходит для значений полей с пробелами.
 – 
Barun Sharma
10 Апр 2015 в 09:17

Все решения, представленные здесь на сегодняшний день, за исключением рабочей среды MySQL, неверны и вполне возможно небезопасны (например, проблемы безопасности) по крайней мере для некоторого возможного содержимого в mysql db.

MYSQL Workbench (и аналогично PHPMyAdmin) предоставляют формально правильное решение, но предназначены для загрузки вывода в местоположение пользователя. Они не так полезны для таких вещей, как автоматизация экспорта данных.

Невозможно сгенерировать надежно правильный CSV из вывода mysql -B -e 'SELECT ...', потому что он не может кодировать возврат каретки и пробелы в полях. Флаг '-s' для mysql выполняет экранирование обратной косой черты и может привести к правильному решению. Однако использование языка сценариев (с приличными внутренними структурами данных, а не bash) и библиотек, в которых проблемы с кодированием уже тщательно проработаны, намного безопаснее.

Я подумал о написании сценария для этого, но как только я подумал о том, как бы это назвать, мне пришло в голову искать ранее существовавшие работы с тем же именем. Хотя я еще не изучил это полностью, решение на https://github.com/robmiller/mysql2csv выглядит многообещающе. В зависимости от вашего приложения подход yaml к определению команд SQL может понравиться, а может и не понравиться. Я также не в восторге от потребности в более свежей версии ruby, которая не входит в стандартную комплектацию моего ноутбука Ubuntu 12.04 или серверов Debian Squeeze. Да, я знаю, что могу использовать RVM, но я бы предпочел не поддерживать его для такой простой цели.

Надеюсь, кто-нибудь подскажет подходящий инструмент, который прошел небольшое тестирование. В противном случае я, вероятно, обновлю это, когда найду или напишу один.

31
mc0e 4 Мар 2019 в 03:34
1
Вы правы, для сложных строк в таблице нужно использовать какую-нибудь приличную библиотеку, а не только bash. Я думаю, что у nodejs есть лучшие решения для такого рода действий. как этот пример
 – 
yeya
28 Июл 2016 в 18:28
1
Привет, хороший ответ, я бы добавил ссылку на решение python, предложенное ниже stackoverflow.com/a/35123787/1504300, который работает хорошо и очень просто. Я пытался отредактировать ваше сообщение, но изменение было отклонено
 – 
reallynice
2 Июн 2017 в 15:44
Сценарий mysql2csv Роба Миллера настаивает на подключении к самой базе данных через сеть или сокет и не может использоваться в качестве конвейера в стиле Unix. Возможно, это необходимо, но это действительно ограничивает использование.
 – 
chrisinmtown
9 Сен 2020 в 22:21
Что бы вы хотели в него вложить? Может быть, вывод myslqldump? Как я уже отмечал, вывод mysql -B не может быть исправлен.
 – 
mc0e
4 Окт 2020 в 17:03
1
Я хочу передать в вывод mysqldump, прочтите это как stdin.
 – 
chrisinmtown
5 Окт 2020 в 16:20

Многие ответы на этой странице являются слабыми, потому что они не рассматривают общий случай того, что может происходить в формате CSV. например запятые и кавычки, вставленные в поля, и другие условия, которые всегда в конце концов возникают. Нам нужно общее решение, которое работает для всех допустимых входных данных CSV.

Вот простое и надежное решение на Python:

#!/usr/bin/env python

import csv
import sys

tab_in = csv.reader(sys.stdin, dialect=csv.excel_tab)
comma_out = csv.writer(sys.stdout, dialect=csv.excel)

for row in tab_in:
    comma_out.writerow(row)

Назовите этот файл tab2csv, поместите его на свой путь, дайте ему права на выполнение, а затем используйте его следующим образом:

mysql OTHER_OPTIONS --batch --execute='select * from whatever;' | tab2csv > outfile.csv

Функции обработки CSV в Python охватывают угловые случаи для входных форматов CSV.

Это можно улучшить для обработки очень больших файлов с помощью потокового подхода.

30
Michael 13 Июн 2019 в 00:26
10
Еще более надежным решением было бы фактическое подключение к базе данных с помощью Python, тогда вам будет легче делать то, что вам нужно сделать, чтобы иметь дело с большими наборами данных (результаты фрагментации, потоковая передача и т. Д.).
 – 
Josh Rumbut
4 Фев 2016 в 18:52
@JoshRumbut, очень поздно, но я сделал stackoverflow.com/a/41840534/2958070, чтобы дополнить ваш комментарий
 – 
Ben
30 Авг 2019 в 19:28
См. stackoverflow.com/questions/356578/… для расширенной версии этого скрипта с входным диалектом, который обрабатывает встроенные символы запятой и двойных кавычек!
 – 
chrisinmtown
10 Сен 2020 в 16:51

Из командной строки вы можете сделать это:

mysql -h *hostname* -P *port number* --database=*database_name* -u *username* -p -e *your SQL query* | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > *output_file_name.csv*

Кредиты: Экспорт таблицы из Amazon RDS в файл csv

25
Community 23 Май 2017 в 15:18
Это один сумасшедший лайнер. шляпа
 – 
Elias Escalante
7 Ноя 2017 в 05:47
  1. логика:

CREATE TABLE () (SELECT data FROM other_table ) ENGINE=CSV ;

Когда вы создаете таблицу CSV, сервер создает файл формата таблицы в каталоге базы данных. Файл начинается с имени таблицы и имеет расширение .frm. Механизм хранения также создает файл данных. Его имя начинается с имени таблицы и имеет расширение .CSV. Файл данных представляет собой простой текстовый файл. Когда вы сохраняете данные в таблице, механизм хранения сохраняет их в файл данных в формате значений, разделенных запятыми.

20
zloctb 7 Май 2014 в 12:41
1
Приятно, так как это правильно, никаких других настроек не требуется.
 – 
Andrew Schulman
4 Янв 2018 в 00:53

В этом ответе используется Python и популярная сторонняя библиотека PyMySQL. Я добавляю его, потому что библиотека Python csv достаточно мощная, чтобы правильно обрабатывают множество различных вариантов .csv, и никакие другие ответы не используют код Python для взаимодействия с базой данных.

import contextlib
import csv
import datetime
import os

# https://github.com/PyMySQL/PyMySQL
import pymysql

SQL_QUERY = """
SELECT * FROM my_table WHERE my_attribute = 'my_attribute';
"""

# embedding passwords in code gets nasty when you use version control
# the environment is not much better, but this is an example
# https://stackoverflow.com/questions/12461484
SQL_USER = os.environ['SQL_USER']
SQL_PASS = os.environ['SQL_PASS']

connection = pymysql.connect(host='localhost',
                             user=SQL_USER,
                             password=SQL_PASS,
                             db='dbname')

with contextlib.closing(connection):
    with connection.cursor() as cursor:
        cursor.execute(SQL_QUERY)
        # Hope you have enough memory :)
        results = cursor.fetchall()

output_file = 'my_query-{}.csv'.format(datetime.datetime.today().strftime('%Y-%m-%d'))
with open(output_file, 'w', newline='') as csvfile:
    # http://stackoverflow.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='\n')
    csv_writer.writerows(results)
17
Michael 13 Июн 2019 в 00:23
Ответ с использованием Python уже был предоставлен. stackoverflow.com/a/35123787/5470883
 – 
Alexander Baltasar
25 Янв 2017 в 12:39
5
@AlexanderBaltasar, верно, и выглядит полезным, но не использует код Python для взаимодействия с базой данных. См. Комментарий к этому вопросу.
 – 
Ben
26 Янв 2017 в 05:29

Это просто, и он работает с чем угодно, не требуя пакетного режима или файлов вывода:

select concat_ws(',',
    concat('"', replace(field1, '"', '""'), '"'),
    concat('"', replace(field2, '"', '""'), '"'),
    concat('"', replace(field3, '"', '""'), '"'))

from your_table where etc;

Пояснение:

  1. Замените " на "" в каждом поле -> replace(field1, '"', '""')
  2. Заключите каждый результат в кавычки -> concat('"', result1, '"')
  3. Ставьте запятую между каждым результатом в кавычках -> concat_ws(',', quoted1, quoted2, ...)

Это оно!

14
Michael 13 Июн 2019 в 00:22
3
Обратите внимание, что значения NULL будут пропущены concat_ws(), что приведет к несоответствию столбца. Чтобы этого избежать, просто используйте вместо нее пустую строку: IFNULL(field, '') (или что-то еще, что вы используете для представления NULL)
 – 
Marco Roy
22 Май 2019 в 02:11

Кроме того, если вы выполняете запрос в командной строке Bash, я считаю, что команду tr можно использовать для замены вкладок по умолчанию на произвольные разделители.

$ echo "SELECT * FROM Table123" | mysql Database456 | tr "\t" ,
13
2240 20 Ноя 2020 в 02:13
Это хороший способ, если у вас возникли проблемы с правами доступа к файлам, но он не будет цитировать ваши поля, поэтому другие инструменты могут неверно интерпретировать CSV, если ваши данные содержат запятые или кавычки.
 – 
Paul A Jungwirth
8 Апр 2021 в 18:29

В качестве альтернативы приведенному выше ответу у вас может быть таблица MySQL, в которой используется механизм CSV.

Тогда у вас будет файл на вашем жестком диске, который всегда будет в формате CSV, который вы можете просто скопировать, не обрабатывая его.

11
Jonathan 11 Дек 2008 в 02:34
2
Каковы ограничения этого с точки зрения размера файла / записи / чтения / и т. Д.?
 – 
Zach Smith
10 Окт 2018 в 11:21

Я столкнулся с той же проблемой, и Ответ Пола не подходил, поскольку это была RDS. Замена вкладки запятыми не сработала, поскольку в данные были встроены запятые и вкладки. Я обнаружил, что mycli, которая является альтернативой для mysql-client, поддерживает вывод csv из коробки с флаг --csv

mycli db_name --csv -e "select * from flowers" > flowers.csv
11
Shenal Silva 16 Фев 2020 в 13:39
Работает как шарм, вы можете установить mycli в macOS через: brew update && brew install mycli. Я больше никогда не использую стандартный клиент mysql, mycli настолько легален!
 – 
bithavoc
24 Июл 2020 в 05:40
1
Mycli и его кузен pgcli фантастические. Я пришел сюда, чтобы добавить этот совет mysql, потому что с другими решениями я ничего не добился. Чистый вывод в локальный .csv с mysql на удивление труден.
 – 
iturgeon
4 Сен 2020 в 22:17
Здорово, так грустно, что этот ответ получил очень мало лайков. Это единственное решение, которое мне подходит. Все остальное не сработало для меня идеально, кроме этого. У меня были разрывы строк в столбцах - и это привело к появлению новых строк в программе Excel при открытии файла.
 – 
Skiff
21 Ноя 2020 в 02:57
Этот ответ не сработает, если вы застряли при использовании версии 1.8.1 (возможно, потому, что вы используете более старую ОС, в которой все еще есть Python 2.x), поскольку '--csv' не был доступен в этой версии.
 – 
Joseph Van Riper
14 Дек 2020 в 12:35

Чтобы расширить предыдущие ответы, следующий однострочный файл экспортирует одну таблицу как файл с разделителями табуляции. Он подходит для автоматизации, экспортируя базу данных каждый день или около того.

mysql -B -D mydatabase -e 'select * from mytable'

Удобно, что мы можем использовать ту же технику для составления списка таблиц MySQL и описания полей в одной таблице:

mysql -B -D mydatabase -e 'show tables'

mysql -B -D mydatabase -e 'desc users'

Field   Type    Null    Key Default Extra
id  int(11) NO  PRI NULL    auto_increment
email   varchar(128)    NO  UNI NULL    
lastName    varchar(100)    YES     NULL    
title   varchar(128)    YES UNI NULL    
userName    varchar(128)    YES UNI NULL    
firstName   varchar(100)    YES     NULL    
10
johntellsall 23 Окт 2014 в 20:09
4
Чтобы преобразовать в CSV: mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
 – 
DSimon
13 Янв 2015 в 00:15
7
Использование sed -e 's/\t/,/g' безопасно только в том случае, если вы уверены, что ваши данные не содержат запятых или табуляций.
 – 
awatts
20 Окт 2015 в 19:23

Основываясь на user7610, вот лучший способ сделать это. С mysql outfile возникли проблемы с владением файлами и перезаписью в течение 60 минут.

Это не круто, но сработало за 5 минут.

php csvdump.php localhost root password database tablename > whatever-you-like.csv

<?php

$server = $argv[1];
$user = $argv[2];
$password = $argv[3];
$db = $argv[4];
$table = $argv[5];

mysql_connect($server, $user, $password) or die(mysql_error());
mysql_select_db($db) or die(mysql_error());

// fetch the data
$rows = mysql_query('SELECT * FROM ' . $table);
$rows || die(mysql_error());


// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');

// output the column headings

$fields = [];
for($i = 0; $i < mysql_num_fields($rows); $i++) {
    $field_info = mysql_fetch_field($rows, $i);
    $fields[] = $field_info->name;
}
fputcsv($output, $fields);

// loop over the rows, outputting them
while ($row = mysql_fetch_assoc($rows)) fputcsv($output, $row);

?>
8
Michael Cole 29 Май 2015 в 21:36
1
Красиво, чисто и быстро работает - это отличное решение, если вы можете запускать PHP в такой среде!
 – 
John Fiala
6 Апр 2018 в 01:01

Вот что я делаю:

echo $QUERY | \
  mysql -B  $MYSQL_OPTS | \
  perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^[\d.]+$/ ? $_ : qq("$_")} @F ' | \
  mail -s 'report' person@address

Сценарий perl (полученный из другого источника) отлично справляется с преобразованием полей с разделителями табуляции в CSV.

7
Mei 9 Мар 2012 в 05:01
2
Отлично. Небольшое улучшение может заключаться в цитировании всего, кроме цифр perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F ' - в вашем случае 1.2.3 цитировать не нужно.
 – 
artfulrobot
15 Мар 2017 в 19:00
1
Это должно быть общепринятым решением IMHO, конечно, с улучшением @artfulrobot.
 – 
chrisinmtown
25 Сен 2020 в 17:55

Не совсем в формате CSV, но tee команду из клиента MySQL можно использовать для сохранения вывода в локальный файл:

tee foobar.txt
SELECT foo FROM bar;

Вы можете отключить его, используя notee.

Проблема с SELECT … INTO OUTFILE …; в том, что ему требуется разрешение на запись файлов на сервере.

5
Denilson Sá Maia 29 Май 2014 в 22:14
Если вместо .txt используется расширение .csv, следует ли помнить о каких-либо проблемах с форматированием?
 – 
datalifenyc
9 Май 2018 в 00:53
Проблемы с форматированием возникают из-за того, что запятые и т. Д. Не экранируются. CSV - это простой текстовый формат, поэтому проблема с форматированием не возникает просто после замены расширения.
 – 
jkmartindale
20 Июн 2019 в 20:24

Используя решение, опубликованное Тимом, я создал этот сценарий bash для облегчения процесса (запрашивается пароль root, но вы можете легко изменить сценарий, чтобы запросить любого другого пользователя):

#!/bin/bash

if [ "$1" == "" ];then
    echo "Usage: $0 DATABASE TABLE [MYSQL EXTRA COMMANDS]"
    exit
fi

DBNAME=$1
TABLE=$2
FNAME=$1.$2.csv
MCOMM=$3

echo "MySQL password:"
stty -echo
read PASS
stty echo

mysql -uroot -p$PASS $MCOMM $DBNAME -B -e "SELECT * FROM $TABLE;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > $FNAME

Будет создан файл с именем: database.table.csv .

3
lepe 16 Май 2013 в 12:04
Как насчет встроенных символов двойных кавычек? От них тоже нужно избавиться, но я не вижу закономерности в заклинании sed для них.
 – 
chrisinmtown
25 Сен 2020 в 17:50

Если на сервере настроен PHP, вы можете использовать mysql2csv для экспорта (действительно действительного ) CSV-файл для произвольного запроса mysql. См. мой ответ в MySQL - SELECT * INTO OUTFILE LOCAL? для получения дополнительной информации / контекста.

Я попытался сохранить имена параметров из mysql, поэтому должно быть достаточно предоставить параметры --file и --query:

./mysql2csv --file="/tmp/result.csv" --query='SELECT 1 as foo, 2 as bar;' --user="username" --password="password"

"Установить" mysql2csv через

wget https://gist.githubusercontent.com/paslandau/37bf787eab1b84fc7ae679d1823cf401/raw/29a48bb0a43f6750858e1ddec054d3552f3cbc45/mysql2csv -O mysql2csv -q && (sha256sum mysql2csv | cmp <(echo "b109535b29733bd596ecc8608e008732e617e97906f119c66dd7cf6ab2865a65  mysql2csv") || (echo "ERROR comparing hash, Found:" ;sha256sum mysql2csv) ) && chmod +x mysql2csv

(загрузите содержание, проверьте контрольную сумму и сделайте его исполняемым).

3
Hirnhamster 16 Май 2018 в 14:31

Следующее производит разделенный табуляцией и действительный вывод в формате CSV. В отличие от большинства других ответов, этот метод правильно обрабатывает экранирование вкладок, запятых, кавычек и новых строк без какого-либо фильтра потока, такого как sed, awk или tr. В примере показано, как передать удаленную таблицу mysql напрямую в локальную базу данных sqlite с помощью потоков. Это работает без разрешения FILE или разрешения SELECT INTO OUTFILE. Я добавил новые строки для удобства чтения.

mysql -B -C --raw -u 'username' --password='password' --host='hostname' 'databasename'
-e 'SELECT
    CONCAT('\''"'\'',REPLACE(`id`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''id'\'',
    CONCAT('\''"'\'',REPLACE(`value`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''value'\''
    FROM sampledata'
2>/dev/null | sqlite3 -csv -separator $'\t' mydb.db '.import /dev/stdin mycsvtable'

2>/dev/null нужен для подавления предупреждения о пароле в командной строке.

Если ваши данные содержат NULL, вы можете использовать в запросе функцию IFNULL ().

3
humbads 17 Июл 2019 в 20:40

Если вы получаете сообщение об ошибке secure-file-priv, то также после изменения местоположения целевого файла внутри C:\ProgramData\MySQL\MySQL Server 8.0\Uploads, а также после этого запроса -

SELECT * FROM attendance INTO OUTFILE 'C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\FileName.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';

Не работает, вам нужно просто изменить \ (backsplash) с запроса на / (forwardsplash)

И это работает !!

Примере:

ВЫБЕРИТЕ * ИЗ посещаемости В OUTFILE 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' ПОЛЯ, ЗАКОНЧЕННЫЕ ',' ЗАКРЫТО '"' СТРОКИ, ЗАКОНЧЕННЫЕ '\ n';

Каждый раз, когда вы запускаете успешный запрос, он каждый раз будет генерировать новый файл csv! Круто, правда?

2
AAYUSH SHAH 20 Дек 2019 в 18:27

В моем случае from table_name ..... перед INTO OUTFILE ..... дает ошибку (Unexpected ordering of clauses. (near "FROM" at position 10)).

Что у меня работает.

SELECT *
INTO OUTFILE '/Volumes/Development/sql/sql/enabled_contacts.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n' 
FROM table_name
WHERE column_name = 'value'
2
Md. Robi Ullah 21 Сен 2020 в 13:12

Крошечный сценарий bash для выполнения простого запроса к дампу CSV, вдохновленный https://stackoverflow.com/a/5395421/2841607 .

#!/bin/bash

# $1 = query to execute
# $2 = outfile
# $3 = mysql database name
# $4 = mysql username

if [ -z "$1" ]; then
    echo "Query not given"
    exit 1
fi

if [ -z "$2" ]; then
    echo "Outfile not given"
    exit 1
fi

MYSQL_DB=""
MYSQL_USER="root"

if [ ! -z "$3" ]; then
    MYSQL_DB=$3
fi

if [ ! -z "$4" ]; then
    MYSQL_USER=$4
fi

if [ -z "$MYSQL_DB" ]; then
    echo "Database name not given"
    exit 1
fi

if [ -z "$MYSQL_USER" ]; then
    echo "Database user not given"
    exit 1
fi

mysql -u $MYSQL_USER -p -D $MYSQL_DB -B -s -e "$1" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > $2
echo "Written to $2"
1
minitauros 1 Мар 2018 в 15:23
Здесь используется заклинание sed, которое игнорирует встроенные символы двойных кавычек. Предложите вместо этого использовать решение perl.
 – 
chrisinmtown
25 Сен 2020 в 17:52

У меня работает следующий сценарий bash. При желании он также получает схему для запрошенных таблиц.

#!/bin/bash
#
# export mysql data to CSV
#https://stackoverflow.com/questions/356578/how-to-output-mysql-query-results-in-csv-format
#

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'
red='\033[0;31m'
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}


#
# error
#
# show the given error message on stderr and exit
#
#   params:
#     1: l_msg - the error message to display
#
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error:" 1>&2
  color_msg $red "\t$l_msg" 1>&2
  usage
}

#
# display usage 
#
usage() {
  echo "usage: $0 [-h|--help]" 1>&2
  echo "               -o  | --output      csvdirectory"    1>&2
  echo "               -d  | --database    database"   1>&2
  echo "               -t  | --tables      tables"     1>&2
  echo "               -p  | --password    password"   1>&2
  echo "               -u  | --user        user"       1>&2
  echo "               -hs | --host        host"       1>&2
  echo "               -gs | --get-schema"             1>&2
  echo "" 1>&2
  echo "     output: output csv directory to export mysql data into" 1>&2
  echo "" 1>&2
  echo "         user: mysql user" 1>&2
  echo "     password: mysql password" 1>&2
  echo "" 1>&2
  echo "     database: target database" 1>&2
  echo "       tables: tables to export" 1>&2
  echo "         host: host of target database" 1>&2
  echo "" 1>&2
  echo "  -h|--help: show help" 1>&2
  exit 1
}

#
# show help 
#
help() {
  echo "$0 Help" 1>&2
  echo "===========" 1>&2
  echo "$0 exports a csv file from a mysql database optionally limiting to a list of tables" 1>&2
  echo "   example: $0 --database=cms --user=scott --password=tiger  --tables=person --output person.csv" 1>&2
  echo "" 1>&2
  usage
}

domysql() {
  mysql --host $host -u$user --password=$password $database
}

getcolumns() {
  local l_table="$1"
  echo "describe $l_table" | domysql | cut -f1 | grep -v "Field" | grep -v "Warning" | paste -sd "," - 2>/dev/null
}

host="localhost"
mysqlfiles="/var/lib/mysql-files/"

# parse command line options
while true; do
  #echo "option $1"
  case "$1" in
    # options without arguments
    -h|--help) usage;;
    -d|--database)     database="$2" ; shift ;;
    -t|--tables)       tables="$2" ; shift ;;
    -o|--output)       csvoutput="$2" ; shift ;;
    -u|--user)         user="$2" ; shift ;;
    -hs|--host)        host="$2" ; shift ;;
    -p|--password)     password="$2" ; shift ;;
    -gs|--get-schema)  option="getschema";; 
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; usage;;
    (*) break;;
  esac
  shift
done

# checks
if [ "$csvoutput" == "" ]
then
  error "ouput csv directory not set"
fi
if [ "$database" == "" ]
then
  error "mysql database not set"
fi
if [ "$user" == "" ]
then
  error "mysql user not set"
fi
if [ "$password" == "" ]
then
  error "mysql password not set"
fi

color_msg $blue "exporting tables of database $database"
if [ "$tables" = "" ]
then
tables=$(echo "show tables" | domysql)
fi

case $option in
  getschema) 
   rm $csvoutput$database.schema
   for table in $tables
   do
     color_msg $blue "getting schema for $table"
     echo -n "$table:" >> $csvoutput$database.schema
     getcolumns $table >> $csvoutput$database.schema
   done  
   ;;
  *)
for table in $tables
do
  color_msg $blue "exporting table $table"
  cols=$(grep "$table:" $csvoutput$database.schema | cut -f2 -d:)
  if [  "$cols" = "" ]
  then
    cols=$(getcolumns $table)
  fi
  ssh $host rm $mysqlfiles/$table.csv
cat <<EOF | mysql --host $host -u$user --password=$password $database 
SELECT $cols FROM $table INTO OUTFILE '$mysqlfiles$table.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
EOF
  scp $host:$mysqlfiles/$table.csv $csvoutput$table.csv.raw
  (echo "$cols"; cat $csvoutput$table.csv.raw) > $csvoutput$table.csv
  rm $csvoutput$table.csv.raw
done
  ;;
esac
1
Wolfgang Fahl 14 Май 2018 в 18:19

Что сработало для меня:

SELECT *
FROM students
WHERE foo = 'bar'
LIMIT 0,1200000
INTO OUTFILE './students-1200000.csv'
FIELDS TERMINATED BY ',' ESCAPED BY '"'
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n';

Ни одно из решений в этом потоке не сработало для моего конкретного случая, у меня были довольно данные json внутри одного из столбцов, которые могли бы испортиться в моем выводе csv. Тем, у кого есть подобная проблема, попробуйте вместо этого строки, заканчивающиеся \ r \ n.

Также еще одна проблема для тех, кто пытается открыть csv с помощью Microsoft Excel, имейте в виду, что существует ограничение в 32 767 символов, которое может содержать одна ячейка, выше этого она переполняется на строки ниже. Чтобы определить, какие записи в столбце имеют проблему, используйте запрос ниже. Затем вы можете обрезать эти записи или обрабатывать их по своему усмотрению.

SELECT id,name,CHAR_LENGTH(json_student_description) AS 'character length'
FROM students
WHERE CHAR_LENGTH(json_student_description)>32767;
5
Rohit Chemburkar 7 Ноя 2018 в 09:15