Есть ли простой способ запустить запрос 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
Это становится беспорядочным, когда есть много столбцов, которые нужно окружить кавычками, или если в результатах есть кавычки, которые нужно экранировать.
Посмотрите мой ответ в [this stackoverflow] [1] [1]: stackoverflow.com/questions/12242772/…
Вы можете Форматировать данные таблицы как текстовую таблицу.
Принятый ответ на этот вопрос о переполнении стека, вероятно, лучший способ: stackoverflow.com/questions/3760631/mysql-delimiter-question
Я написал запрос функции на трекере ошибок MariaDB (jira.mariadb.org/browse/MDEV-12879). Вы можете проголосовать за него.
Скопировано из удаленного ответа ниже: SELECT @@GLOBAL.secure_file_priv; покажет вам путь, к которому у вас есть доступ. У меня не было доступа на запись к /tmp/, но у меня был доступ к /var/lib/mysql-files/.
Возможный ответ, если у вас нет доступа на запись на сервере: 1) Используйте mysqldump для дампа таблицы. 2) Импортируйте таблицу в вашу локальную базу данных. 3) Используйте принятый ответ для экспорта (select ... into outfile) в CSV.
Я предполагаю, что вы имеете в виду без программного кода, верно?






От 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';
При использовании этой команды имена столбцов не будут экспортированы.
Также обратите внимание, что /var/lib/mysql-files/orders.csv будет находиться на сервер, на котором работает MySQL. Пользователь, под которым запущен процесс MySQL, должен иметь разрешения на запись в выбранный каталог, иначе команда завершится ошибкой.
Если вы хотите записать вывод на локальную машину с удаленного сервера (особенно с размещенной или виртуализированной машины, такой как Heroku или Amazon RDS), это решение не подходит.
@TomasT. Ниже приведен ряд решений, позволяющих использовать разделители табуляции вместо CSV. Например, Excel может принимать как CSV, так и файлы с разделителями табуляции и конвертировать один в другой.
@Tomas, если у вас есть доступ к удаленной файловой системе и MySQL, вы должны иметь возможность писать где-нибудь. вместо / tmp попробуйте /home/yourusername/file.csv - если это не удается, а набор результатов не такой большой, вы можете скопировать вывод из вашего SSH-клиента и вставить его на свой локальный компьютер.
К сожалению, это никоим образом не соответствует стандартам
В вопросе указан MySQL, а не "совместимый со стандартами".
Как включить заголовок?
На компьютере с Windows строка OUTFILE должна избегать обратной косой черты. Например, я использовал строку 'C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\output\\orders.csv'
@BogdanGusiev, вы можете включить заголовок, добавив "SELECT 'order_id', 'product_name', 'qty' UNION" перед реальным запросом. Первый запрос выбора возвращает заголовок, второй запрос возвращает реальные данные; UNION объединяет все воедино.
@BogdanGusiev посмотрите lifeboysays.wordpress.com/2012/06/23/…
@ Майкл Батлер: Вообще-то нет. Если вы используете Amazon RDS, Heroku или любое другое размещенное решение, вы вряд ли сможете просто писать на чужой сервер.
что, если вы хотите использовать его после присоединения? ВЫБЕРИТЕ order_id, product_name, qty ИЗ заказов INTO OUTFILE '/tmp/orders.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\ n' присоедините x как x на xx.id = test.id
@Tomas: Я написал инструмент специально для этого. См. этот ответ StackOverflow.
Администраторам БД следует хорошенько подумать, прежде чем предоставлять разрешение File_priv, необходимое для работы этого подхода. См. docs.oracle.com/cd/E17952_01/refman-5.0-en/…
@TMS, для этого еще нужна привилегия "предоставить файл", см. Также stackoverflow.com/questions/6091427/…
Если у вас много столбцов и они все нужны: SELECT column_name FROM information_schema.columns WHERE table_name = 'orders' INTO OUTFILE '/tmp/orders_columns.csv' FIELDS TERMINATED BY '' ENCLOSED BY '"' LINES TERMINATED BY ',';
вы можете использовать опцию экспорта myadmin для файла csv
В Windows расположение файла xampp: C: \ xampp \ mysql \ data \ <databasename> _ <month> \ orders.csv (INTO OUTFILE 'urls1.csv')
Не забывайте о разрешениях. Мне пришлось поместить свой файл Outfile в / tmp. mysql не имеет прав на запись в мой рабочий каталог. Вот мой запрос> выберите * из daily_reads, где DeviceID = 80632679 и LoadDateLocal> '2015-06-01 00:00:00', в поля outfile '/tmp/80632679_reads_since_060115.csv', оканчивающиеся строками ',', заключенными в '' ' заканчивается '\ r \ n';
Это решение работает только тогда, когда у вас есть доступ к файловой системе сервера MYSQL, то есть у вас есть прямой административный доступ к этому серверу (и вы не против заполнить его диск экспортируемыми данными). Это не решение, если у пользователя нет доступа к серверу, например. пользователь не является администратором, или пользователь является администратором, но база данных работает удаленно, например. в AWS.
Я не думаю, что это хорошо работает, если в ваших записях есть разрывы строк или двойные кавычки ... Кажется, не существует способа заменить "на" "(который, как мне кажется, является обычным в CSV) в выводе без также экранирование разрывов строк.
@styfle, ну, в Windows вы можете попробовать / в качестве разделителя, например 'C:/wamp/bin/mysql/mysql5.5.24/bin/output/orders.csv', у меня это работает.
Имейте в виду, что если у вас строгие настройки, вы можете получить следующее: ОШИБКА 1290 (HY000): сервер MySQL работает с параметром --secure-file-priv, поэтому он не может выполнить этот оператор.
Если mysql работает с --secure-file-priv, вы, скорее всего, не сможете писать на /tmp. Запустите SHOW VARIABLES LIKE "secure_file_priv";, чтобы увидеть, в какой каталог вы можете писать.
Я использовал [SQLyog] (webyog.com/product/sqlyog) для экспорта в CSV. Это довольно просто.
@PaulTomblin, как я могу экспортировать его с именем столбца?
Какая польза от CSV без заголовков столбцов?
Учитывая, что OP конкретно поднимает проблемы, возникающие при цитировании, насколько этот ответ правильный? Что делать, если в одном из значений есть "?
@ mc0e Я почти уверен, что есть предложение ESCAPED BY, которое вы можете использовать, если у вас есть поля, в которых могут быть кавычки. stackoverflow.com/a/2859026/3333
@petrkotek UNION не гарантирует порядок; ваш заголовок может оказаться нижним колонтитулом
Мне пришлось использовать это для импорта в Postgres, потому что MySQL использует '\' для экранирования символов, таких как \" и \\r. \copy table (field1, field2, created_at, updated_at) from 'files/table.csv' with (format csv, header true, escape e'\\'); (я вручную вставил заголовок с помощью Notepad ++.) stackoverflow.com/questions/7484413/ddg#7495514
Каждый сервер mysql, которого я касаюсь, имеет файл с именем /var/lib/mysql-files/orders.csv, потому что каждый раз, когда мне нужно экспортировать в CSV, я копирую и вставляю из этого ответа.
Ошибка выдачи: [HY000] [1290] Сервер MySQL работает с параметром --secure-file-priv, поэтому он не может выполнить этот оператор.
Есть ли способ создать файл только в том случае, если запрос что-то возвращает? и ничего не создавать, если количество строк = 0?
@PaulTomblin Относительно того же, если я запускаю следующий запрос, я получаю сообщение об ошибке. Мой запрос: justpaste.it/2fp6f Любая помощь, спасибо.
Фу! Есть ли способ сделать это без отправки в файл ???
@Michael попробуйте синтаксис без части INTO OUTFILE.
Я получаю ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement , не совсем понимаю, почему
как заставить его добавляться в тот же файл, если мы используем итерацию / цикл.
Я создал файл csv (большой файл) и попытался загрузить его с помощью pandas. read_csv получил эту ошибку: Ошибка токенизации данных. Ошибка C: ожидалось 5 полей в строке 460308, видели 6 предложений?
В качестве альтернативы приведенному выше ответу у вас может быть таблица MySQL, в которой используется механизм CSV.
Тогда у вас будет файл на вашем жестком диске, который всегда будет в формате CSV, который вы можете просто скопировать, не обрабатывая его.
Каковы ограничения этого с точки зрения размера файла / записи / чтения / и т. д.?
mysql --batch, -B
Print results using tab as the column separator, with each row on a new line. With this option, mysql does not use the history file. Batch mode results in non-tabular output format and escaping of special characters. Escaping may be disabled by using raw mode; see the description for the --raw option.
Это даст вам файл, разделенный табуляцией. Поскольку запятые (или строки, содержащие запятую) не экранируются, изменить разделитель на запятую непросто.
это предпочтительное решение: 1) списки значений, разделенных табуляцией, распространены в UNIX 2) Импорт TSV изначально поддерживается большинством систем импорта, включая Excel, таблицы OpenOffice и т. д. 3) нет необходимости экранировать символы кавычек для текстовых полей 4 ) упрощает экспорт из командной строки
это лучшее решение, потому что, в отличие от первого, не нужно иметь разрешений на серверах, таких как RDS.
Изящный трюк: если вы сохраните файл с разделением табуляцией как .xls вместо .csv, он откроется в Excel без необходимости преобразования «текста в данные» и без каких-либо проблем с региональными настройками.
@Joey T - вам все еще нужно избегать табуляции и возврата каретки. Кроме того, если содержимое поля выглядит как поле в кавычках или экранированных полях, импортированное содержимое может отличаться от оригинала.
Спасибо, это мне очень поможет в будущем! CLI --help только говорит: -B, --batch: не использовать файл истории. Отключить интерактивное поведение. (Включает --silent.) Поэтому я всегда упускал из виду эту опцию, когда искал "простой" формат экспорта.
Я использую это в сочетании с отличной утилитой xsv [github.com/BurntSushi/xsv] для преобразования в CSV
у вас будет проблема с NULL .. они будут отображаться как строковые нули ..
Вы можете пропустить заголовки столбцов, используя -N или --skip-column-names.
Я обнаружил, что --batch не экранирует символы новой строки последовательно, иногда как \n, иногда как перевод строки, за которым следует \n.
$ mysql your_database --password=foo < my_requests.sql > out.csv
Это разделено табуляцией. Подключите его вот так, чтобы получить настоящий CSV (спасибо @therefromhere):
... .sql | sed 's/\t/,/g' > out.csv
не только это, но и позволяет создавать контент с удаленного хоста базы данных, в отличие от другого способа записи в локальную файловую систему.
Он разделен табуляцией, а не запятой.
@Flimm, при условии, что у вас нет встроенных запятых / вкладок в полях, вы можете преобразовать его, передав результат в | sed 's/\t/,/g'
Я добавил -B для хорошей оценки, но разделение табуляцией для меня так же хорошо, как и разделение запятыми.
Довольно интересно. Почему вывод этой команды в> out.csv отличается от вывода на стандартный вывод, если не указано перенаправление файлов?
sed 'fix' не компенсирует запятые, которые могут появиться в любых выбранных данных, и будет искажать ваши столбцы, выводимые соответствующим образом
Есть ли решение для точки @ JoeyT? У меня есть запятые в некоторых полях, что, очевидно, перемещает вывод в следующий столбец
@NathanWaters Да, используйте переключатель -B (пакетный), упомянутый в предыдущем решении, вместо того, чтобы изменять результаты с помощью sed.
Это нормально для некоторых данных, но если у вас есть произвольные текстовые поля или двоичные данные, это неправильно. например, ваши поля могут включать табуляцию, возврат каретки, обратную косую черту или кавычки.
Негатив действителен ... он может сработать для вас сейчас, но он вполне может укусить вас в будущем, когда ваши данные включают табуляцию, запятую и т. д.
Один трюк, если вам нужно открыть результирующий файл CSV в Excel, и у вас потенциально есть символы-разделители в ваших данных, - это переименовать выходной файл с расширением txt - полученный текстовый импорт в Excel по какой-то причине более склонен к разделению данных правильно.
sed 's / ^ / \ "/ g; s / \ t / \", \ "/ g; s / $ / \" / g'
OP специально выразил озабоченность по поводу цитирования данных, поэтому этот ответ в значительной степени неверен.
Mac OSX не поддерживает \t. Вы можете вставить литерал табуляции, используя ctrl + v, затем tab
Я не смог использовать принятый ответ, потому что получил ошибку Access denied. Это решение сработало для меня.
| tr '\t' ',' у меня работал лучше. Сед, похоже, не подходил для этого дела.
Я получаю пустой CSV-файл. полностью пустой
Решение OUTFILE, данное Полом Томблином, вызывает запись файла на самом сервере MySQL, поэтому это будет работать, только если у вас есть доступ ФАЙЛ, а также доступ для входа в систему или другие средства для извлечения файла из этого ящика.
Если у вас нет такого доступа и вывод с разделителями табуляции является разумной заменой CSV (например, если ваша конечная цель - импортировать в Excel), тогда решение Сербаута (с использованием mysql --batch и, возможно, --raw) - это то, что вам нужно.
Вот довольно грубый способ сделать это. Нашел где-то, не могу взять кредит
mysql --user=wibble --password wobble -B -e "select * from vehicle_categories;" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > vehicle_categories.csv
Работает неплохо. Еще раз, хотя регулярное выражение доказывает только запись.
Объяснение регулярного выражения:
Итак, собираем все вместе:
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
Флаг -e был именно тем, что я искал! Спасибо!
Это регулярное выражение на самом деле довольно просто; как и многие другие ответы на этой странице, он просто очищает вывод mysql -B. Если вы разделите регулярное выражение на отдельные операторы в отдельных строках, это будет довольно просто (для тех, кто знает регулярные выражения), для понимания.
Отлично работает! Важно сказать, что заголовки уже включены (никаких дополнительных действий не требуется).
На первый взгляд, это выглядит довольно сломанным. Табуляция и возврат каретки в содержимом будут неправильно обработаны. "s / '/ \' /;" вообще ничего не делает, потому что двойные кавычки в команде оболочки используют обратную косую черту. Многие другие похожие ошибки с обратной косой чертой теряются. Нет обработки обратной косой черты в поле db.
Похоже, эта команда хорошо работает в Linux, но не в Mac
Это сломается, если у вас есть текстовое поле, содержащее табуляции, обратную косую черту, "," и ряд других вещей. Регулярное выражение - это нет способ решить эту проблему
Предлагаю это ... | sed 's / "/ \" / g' | sed "s / '/ \' /; s / \ t / \", \ "/ g; s / ^ / \" /; s / $ / \ "/; s / \ n // g" ...
это на самом деле намного лучше и быстрее в некоторых случаях, чем внутренний экспорт CSV mysql. красиво сделано!
Это работает, когда у меня нет прав администратора, спасибо.
Вот что я делаю:
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.
Это здорово. Небольшое улучшение может заключаться в цитировании всего, кроме чисел perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F ' - ваш не цитирует 1.2.3
Это должно быть общепринятым решением IMHO, конечно, с улучшением @artfulrobot.
Как насчет:
mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv
Мне это очень нравится. Он намного чище, и мне нравится использовать awk. Однако я бы, наверное, пошел с этим: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS = " = ";} {print $1,$2}' > out.csv
Это не подходит для значений полей с пробелами.
Это просто, и он работает с чем угодно, не требуя пакетного режима или файлов вывода:
select concat_ws(',',
concat('"', replace(field1, '"', '""'), '"'),
concat('"', replace(field2, '"', '""'), '"'),
concat('"', replace(field3, '"', '""'), '"'))
from your_table where etc;
Объяснение:
" на "" в каждом поле -> replace(field1, '"', '""')concat('"', result1, '"')concat_ws(',', quoted1, quoted2, ...)Вот и все!
Обратите внимание, что значения NULL будут пропущены concat_ws(), что приведет к несоответствию столбцов. Чтобы этого избежать, просто используйте вместо нее пустую строку: IFNULL(field, '') (или что-то еще, что вы используете для представления NULL)
Если на используемом вами компьютере установлен PHP, вы можете написать для этого сценарий PHP. Это требует, чтобы при установке PHP было установлено расширение MySQL.
Вы можете вызвать интерпретатор PHP из командной строки следующим образом:
php --php-ini path/to/php.ini your-script.php
Я включаю переключатель --php-ini, потому что вам может понадобиться использовать вашу собственную конфигурацию PHP, которая включает расширение MySQL. В PHP 5.3.0+ это расширение включено по умолчанию, поэтому больше нет необходимости использовать конфигурацию для его включения.
Затем вы можете написать свой экспортный скрипт, как любой обычный PHP-скрипт:
<?php
#mysql_connect("localhost", "username", "password") or die(mysql_error());
mysql_select_db("mydb") or die(mysql_error());
$result = mysql_query("SELECT * FROM table_with_the_data p WHERE p.type = $typeiwant");
$result || die(mysql_error());
while($row = mysql_fetch_row($result)) {
$comma = false;
foreach ($row as $item) {
# Make it comma separated
if ($comma) {
echo ',';
} else {
$comma = true;
}
# Quote the quotes
$quoted = str_replace("\"", "\"\"", $item);
# Quote the string
echo "\"$quoted\"";
}
echo "\n";
}
?>
Преимущество этого метода в том, что у него нет проблем с varchar и текстовыми полями, в которых есть текст, содержащий символы новой строки. Эти поля правильно заключены в кавычки, и эти символы новой строки в них будут интерпретироваться программой чтения CSV как часть текста, а не как разделители записей. Это то, что потом трудно исправить с помощью sed или около того.
Это далеко не излишне сложное решение, это единственное решение, которое идет в правильном направлении, хотя и требует немного большей работы. CSV сложнее, чем кажется на первый взгляд, и вы допустили множество ошибок. например, обратная косая черта в оригинале. Лучше использовать библиотеку, которая проработала все вопросы для записи в CSV.
@ mc0e Обычно кавычки удваиваются или экранируются. Я решил удвоить кавычки, поэтому escape-символ мне не нужен. В разных программах разные представления о деталях CSV. Например, LOAD DATA в MySQL действительно обрабатывает \ как escape-символ, тогда как Open Office Calc - нет. Когда я писал ответ, я экспортировал данные в электронную таблицу.
Мой код обрабатывает все, что было необходимо для экспорта набора данных мой в тот же день;) Ваш ответ также является шагом в правильном направлении, но, как говорится в первом комментарии, он должен 1) подключиться к базе данных sql из сценария напрямую как а также 2) используйте подходящую библиотеку csv.
MySQL Workbench может экспортировать наборы записей в CSV и, кажется, очень хорошо обрабатывает запятые в полях. CSV открывается в OpenOffice нормально.
Спасибо большое, Дэвид. Потратив 3 часа на то, чтобы новые строки выводились правильно для HTML-содержимого в данных, я использовал MySQL Workbench и через 2 минуты у меня был готов мой CSV-файл.
Я только что обнаружил, что его можно сохранять и в формате XML, и это здорово. Я надеюсь перейти от одного приложения к другому, используя XSLT для преобразования этого XML в файл CSV, подходящий для импорта в целевое приложение.
Инструментальная среда mysql - лучший вариант для функции импорта и экспорта.
Хорошо, но каждый раз, когда рабочая среда ограничивает количество выбранных записей до 1000, и когда дело доходит до гораздо большего количества записей, она работает не так хорошо, то же условие для импорта часто блокируется, если я пытаюсь импортировать относительно большой файл csv в База данных mysql с помощью верстака.
Я только что успешно экспортировал более полумиллиона строк с помощью mysql workbench, поэтому большие файлы не кажутся проблемой. Вам просто нужно убедиться, что вы удалили ограничение выбора перед запуском вашего запроса, и вам также может потребоваться увеличить следующие значения в вашем файле my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
В рабочей среде MySQL возникает неприятная утечка памяти при экспорте данных в CSV, если у вас есть большой набор данных, например, еще 1 или 2 миллиона строк, 12 ГБ ОЗУ (проверено на моей машине Linux) недостаточно, и память не очищается, если вы убить или остановить. Для большого набора данных это не решение.
Только для Unix / Cygwin, пропустите его через 'tr':
mysql <database> -e "<query here>" | tr '\t' ',' > data.csv
Примечание: при этом не обрабатываются ни встроенные запятые, ни встроенные вкладки.
Используя решение, опубликованное Тимом, я создал этот сценарий 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
как насчет встроенных символов двойных кавычек? От них тоже нужно избавиться, но я не вижу закономерности в заклинании sed для них.
Все решения, представленные здесь на сегодняшний день, за исключением рабочей среды 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, но я бы предпочел не поддерживать его для такой простой цели.
Надеюсь, кто-нибудь подскажет подходящий инструмент, который прошел небольшое тестирование. В противном случае я, вероятно, обновлю это, когда найду или напишу один.
Вы правы, для сложных строк в таблице нужно использовать какую-нибудь приличную библиотеку, а не только bash. Я думаю, что у nodejs есть лучшие решения для такого рода действий. вот так пример
Привет, хороший ответ, я бы добавил ссылку на решение python, предложенное ниже stackoverflow.com/a/35123787/1504300, которое работает хорошо и очень просто. Я пытался отредактировать ваше сообщение, но изменение было отклонено
Сценарий mysql2csv Роба Миллера настаивает на подключении к самой базе данных через сеть или сокет и не может использоваться в качестве конвейера в стиле Unix. Возможно, это необходимо, но это действительно ограничивает использование.
@chrisinmtown, что бы вы хотели в него вложить? Может быть, вывод myslqldump? Как я уже отмечал, вывод mysql -B не может быть исправлен.
@ mc0e Я хочу передать в вывод mysqldump, прочтите это как stdin.
Это может быть полезно для экспорта целых таблиц в csv, но это не позволяет вам получать результаты запросов, поэтому вы не можете использовать большую часть мощности механизма mysql таким образом.
CREATE TABLE () (SELECT data FROM other_table ) ENGINE=CSV ;
When you create a CSV table, the server creates a table format file in the database directory. The file begins with the table name and has an .frm extension. The storage engine also creates a data file. Its name begins with the table name and has a .CSV extension. The data file is a plain text file. When you store data into the table, the storage engine saves it into the data file in comma-separated values format.
Приятно, так как это правильно, никаких других настроек не требуется.
Не совсем как формат CSV, но tee команда из MySQL клиент можно использовать для сохранения вывода в файл местный:
tee foobar.txt
SELECT foo FROM bar;
Вы можете отключить его с помощью notee.
Проблема с SELECT … INTO OUTFILE …; в том, что ему требуется разрешение на запись файлов на сервере.
Если вместо .txt используется расширение .csv, следует ли помнить о каких-либо проблемах с форматированием?
@myidealab Проблемы с форматированием возникают из-за того, что запятые и т. д. не экранируются. CSV - это простой текстовый формат, поэтому проблема с форматированием не возникает просто после замены расширения.
Попробуйте этот код:
SELECT 'Column1', 'Column2', 'Column3', 'Column4', 'Column5'
UNION ALL
SELECT column1, column2,
column3 , column4, column5 FROM demo
INTO OUTFILE '/tmp/demo.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
Для получения дополнительной информации: http://dev.mysql.com/doc/refman/5.1/en/select-into.html
Относитесь к тому же, если я запускаю следующий запрос, я получаю сообщение об ошибке. Мой запрос: justpaste.it/2fp6f Любая помощь, спасибо. @Indrajeet Singh
Чтобы расширить предыдущие ответы, следующий однострочный файл экспортирует одну таблицу как файл с разделителями табуляции. Он подходит для автоматизации, экспортируя базу данных каждый день или около того.
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
Чтобы преобразовать в CSV: mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
Использование sed -e 's/\t/,/g' безопасно только в том случае, если вы уверены, что ваши данные не содержат запятых или табуляций.
Основываясь на 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);
?>
Красиво, чисто и быстро работает - это отличное решение, если вы можете запускать PHP в такой среде!
В командной строке ты можешь сделать это:
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
это один сумасшедший лайнер. шляпа
Это меня пару раз спасало. Быстро и работает!
--batchPrint results using tab as the column separator, with each row on a new line.
--rawdisables character escaping (\n, \t, \0, and \)
Пример:
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
Если я чего-то не упускаю, создается файл TSV, а не файл CSV ...
@PressingOnAlways Да. Цитата из документа MySQL: «Печатайте результаты, используя табуляцию в качестве разделителя столбцов, с каждой строкой на новой строке». Но при синтаксическом анализе не должно возникнуть проблем с каким-либо разделителем. Я использовал его для создания файлов Excel для своего клиента.
Многие ответы на этой странице являются слабыми, потому что они не рассматривают общий случай того, что может происходить в формате 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.
Это можно улучшить для обработки очень больших файлов с помощью потокового подхода.
Еще более надежным решением было бы фактическое подключение к базе данных с помощью Python, тогда вам будет легче делать то, что вам нужно сделать, чтобы иметь дело с большими наборами данных (результаты фрагментации, потоковая передача и т. д.).
@JoshRumbut, очень поздно, но я сделал stackoverflow.com/a/41840534/2958070, чтобы дополнить ваш комментарий
Пожалуйста, смотрите stackoverflow.com/questions/356578/… для расширенной версии этого скрипта с входным диалектом, который обрабатывает встроенные символы запятой и двойных кавычек!
В этом ответе используется 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)
Ответ с использованием Python уже был предоставлен. stackoverflow.com/a/35123787/5470883
@AlexanderBaltasar, верно, и выглядит полезным, но не использует код Python для взаимодействия с базой данных. См. Комментарий к этому вопросу.
Кроме того, если вы выполняете запрос в командной строке Bash, я считаю, что команду tr можно использовать для замены вкладок по умолчанию на произвольные разделители.
$ echo "SELECT * FROM Table123" | mysql Database456 | tr "\t" ,
Крошечный сценарий 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"
Здесь используется заклинание sed, которое игнорирует встроенные символы двойных кавычек. Предложите вместо этого использовать решение perl.
У меня работает следующий сценарий 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
Если у вас установлен PHP на сервере, вы можете использовать mysql2csv для экспорта (фактически действительного) файла CSV для произвольного запроса mysql. См. мой ответ в MySQL - ВЫБЕРИТЕ * 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
(загрузите содержание, проверьте контрольную сумму и сделайте его исполняемым).
Вы можете использовать следующую команду из редактора SQL / Терминала:
«mysql -h (имя хоста / IP>) -u (имя пользователя) -p (пароль) имя базы данных <(query.sql)> outputFILE (.txt / .xls)»
например имя хоста -x.x.x.x
uname - имя пользователя
пароль - пароль
DBName - employeeDB
queryFile - employee.sql
outputFile - outputFile.xls
mysql -hx.x.x.x -uusername -ppassword employeeDB <employee.sql> outputFile.xls
Убедитесь, что вы выполняете команду из каталога, в котором находится SQL-запрос, или укажите полный путь к местоположению sql-запроса в приведенной выше команде.
Что сработало для меня:
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;
Следующее производит вывод разделенный табуляцией и действительный 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 ().
Если вы работаете на производственном или любом другом сервере без доступа к файловой системе, вы можете использовать этот простой трюк и немного вручную, чтобы получить то, что вы хотите.
Шаг 1. Просто оберните все столбцы под CONCAT и используйте опцию as CSVFormat, предоставленную MySQL, чтобы получить результаты с разделителями-запятыми. (или используйте любой разделитель, который хотите). Вот пример:
SELECT
CONCAT(u.id,
',',
given,
',',
family,
',',
email,
',',
phone,
',',
ua.street_number,
',',
ua.route,
',',
ua.locality,
',',
ua.state,
',',
ua.country,
',',
ua.latitude,
',',
ua.longitude) AS CSVFormat
FROM
table1 u
LEFT JOIN
table2 ua ON u.address_id = ua.id
WHERE
role_policy = 31 and is_active = 1;
Шаг 2. Скопируйте результаты из вашего терминала в файл и очистите все символы вертикальной черты (которые формируют макет ваших результатов) с помощью любого текстового редактора.
Шаг 3. Сохраните как файл .csv и все.
Это решение подвержено ошибкам и не рекомендуется. Вместо этого используйте один из встроенных методов MySQL для извлечения действительного вывода CSV.
Если вы получаете сообщение об ошибке 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)
И это работает !!
Пример:
SELECT * FROM attendance INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/FileName.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
Каждый раз, когда вы запускаете успешный запрос, он каждый раз будет генерировать новый файл csv! Круто, правда?
Это решение помещает SQL-запрос в heredoc и направляет вывод через фильтр:
$cat query.sh
#!/bin/bash
mysql --defaults-group-suffix=[DATABASE_NAME] --batch << EOF | python query.py
SELECT [FIELDS]
FROM [TABLE]
EOF
Эта версия фильтра python работает без использования модуля csv:
$cat query.py
import sys
for line in sys.stdin:
print(','.join(["\"" + str(element) + "\"" for element in line.rstrip('\n').split('\t')]))
Эта версия фильтра python использует модуль csv и включает немного больше кода, но, возможно, немного более понятна:
$cat query.py
import csv, sys
csv_reader = csv.reader(sys.stdin, delimiter='\t')
csv_writer = csv.writer(sys.stdout, quoting=csv.QUOTE_NONNUMERIC)
for line in csv_reader:
csv_writer.writerow(line)
Или вы можете использовать панды:
$cat query.py
import csv, sys
import pandas as pd
df = pd.read_csv(sys.stdin, sep='\t')
df.to_csv(sys.stdout, index=False, quoting=csv.QUOTE_NONNUMERIC)
Я столкнулся с той же проблемой, и Ответ Павла не подходил, так как это был RDS. Замена вкладки запятыми не сработала, поскольку в данные были встроены запятые и вкладки. Я обнаружил, что микли, который является альтернативой для mysql-client, поддерживает вывод csv из коробки с флагом --csv
mycli db_name --csv -e "select * from flowers" > flowers.csv
Работает как шарм, вы можете установить mycli в macOS через: brew update && brew install mycli. Я больше никогда не использую стандартный клиент mysql, mycli настолько легален!
Mycli и его кузен pgcli фантастические. Я пришел сюда, чтобы добавить этот совет mysql, потому что с другими решениями я ничего не добился. Чистый вывод в локальный .csv с mysql на удивление труден.
Здорово, так грустно, что этот ответ получил очень мало лайков. Это единственное решение, которое мне подходит. Все остальное не сработало для меня идеально, кроме этого. У меня были разрывы строк в столбцах - и это привело к появлению новых строк в программе Excel при открытии файла.
Этот ответ не сработает, если вы застряли при использовании версии 1.8.1 (возможно, потому, что вы используете более старую ОС, в которой все еще есть Python 2.x), поскольку '--csv' не был доступен в этой версии.
Для тех, кто может захотеть скачать результат запроса в формате CSV, но не имеет доступа к файлу сервера, но к базе данных. Во-первых, это не команда linux. Шаги ниже:
Create VIEW v as (Select * from user where status = 0))view вашей базы данных.CSV.Export method: на Custom - display all possible options и отметьте Put columns names in the first row.Если вы получаете эту ошибку при попытке экспортировать файл
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
и вы не можете решить эту ошибку. Вы можете сделать одно, просто запустив этот скрипт Python
import mysql.connector
import csv
con = mysql.connector.connect(
host = "localhost",
user = "root",
passwd = "Your Password"
)
cur = con.cursor()
cur.execute("USE DbName")
cur.execute("""
select col1,col2 from table
where <cond>
""")
with open('Filename.csv',mode='w') as data:
fieldnames=["Field1","Field2"]
writer=csv.DictWriter(data,fieldnames=fieldnames)
writer.writeheader()
for i in cur:
writer.writerow({'Field1':i[0],'Field2':i[1]})
Добро пожаловать в Stack Overflow! Это не отвечает на вопрос. Пожалуйста, просмотрите stackoverflow.com/help/how-to-answer.
Стоя на плечах @ChrisJohnson, я расширил ответ от февраля 2016 года на собственный диалект для чтения. Этому инструменту конвейера оболочки не нужно подключаться к вашей базе данных, он обрабатывает случайные запятые и кавычки на входе и прекрасно работает в Python2 а также Python3!
#!/usr/bin/env python
import csv
import sys
# fields are separated by tabs; double-quotes may occur anywhere
csv.register_dialect("mysql", delimiter = "\t", quoting=csv.QUOTE_NONE)
tab_in = csv.reader(sys.stdin, dialect = "mysql")
comma_out = csv.writer(sys.stdout, dialect=csv.excel)
for row in tab_in:
# print("row: {}".format(row))
comma_out.writerow(row)
Используйте этот оператор печати, чтобы убедиться, что он правильно анализирует ваш ввод :)
Главное предостережение: обработка символов возврата каретки, ^ M aka control-M, \ r в терминах Linux. Альтернативный вывод Mysql в пакетном режиме правильно экранирует встроенные символы новой строки, поэтому действительно есть одна строка на строку (определенная символом новой строки linux \ n), mysql не помещает в кавычки данные столбца. Если элемент данных имеет встроенный символ возврата каретки, csv.reader отклоняет этот ввод с этим исключением:
new-line character seen in unquoted field -
do you need to open the file in universal-newline mode?
Пожалуйста, не @ мне говорите, что я должен использовать универсальный файловый режим, повторно открыв sys.stdin.fileno с режимом 'rU'. Я пробовал это, это приводит к тому, что встроенные символы \ r обрабатываются как маркеры конца записи, поэтому одна входная запись неправильно преобразовывается во множество неполных выходных записей. Я не нашел решения Python для этого ограничения модуля Python csv.reader. Я думаю, что основной причиной является реализация / ограничение csv.reader, указанное в их документации https://docs.python.org/3/library/csv.html#csv.reader:
The reader is hard-coded to recognise either '\r' or '\n' as end-of-line,
and ignores lineterminator.
Слабое и неудовлетворительное решение, которое я могу предложить, - это изменить каждый символ \ r на двухсимвольную последовательность '\ n' до того, как Python csv.reader увидит данные. Я использовал команду sed. Вот пример конвейера с выбором mysql и скриптом python сверху:
mysql -u user db --execute = "select * from table where id=12345" \
| sed -e 's/\r/\\n/g' \
| mysqlTsvToCsv.py
После некоторой борьбы с этим я думаю, что Python - неправильное решение. Если вы можете жить с perl, я думаю, что однострочный сценарий, предлагаемый @artfulrobot, может быть наиболее эффективным и простым решением.
В моем случае 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'
Вы можете использовать
REPLACE()в своем запросе, чтобы экранировать кавычки.