Как вывести результаты запроса MySQL в формате CSV?


1183

Есть ли простой способ выполнить запрос 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

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


1
Вы можете использовать REPLACE()в своем запросе экранирование кавычек.
DSM

Посмотрите на мой ответ в [этот stackoverflow] [1] [1]: stackoverflow.com/questions/12242772/…
biniam


2
Принятый ответ на этот вопрос stackoverflow, вероятно, является наилучшим способом: stackoverflow.com/questions/3760631/mysql-delimiter-question
Самуэль Ослунд

Я написал запрос на функцию отслеживания ошибок MariaDB ( jira.mariadb.org/browse/MDEV-12879 ). Вы можете проголосовать за него.
Джаред Бек

Ответы:


1761

С 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), это решение не подходит.


16
@ Томас, если у вас есть доступ к удаленной файловой системе и MySQL, вы должны иметь возможность писать куда-нибудь. вместо / tmp попробуйте /home/yourusername/file.csv - если это не удастся, а набор результатов не так велик, вы можете скопировать вывод из вашего SSH-клиента и вставить на локальный компьютер.
Майкл Батлер

63
Вопрос задан MySQL, а не "соответствует стандартам".
Пол Томблин

35
Как включить заголовок?
Богдан Гусиев

66
@BogdanGusiev, вы можете включить заголовок, добавив "SELECT 'order_id'," product_name "," qty 'UNION "перед реальным запросом. Первый запрос select возвращает заголовок, второй запрос возвращает реальные данные; СОЮЗ объединяет это.
Петркотек

19
@ Майкл Батлер: Нет, вообще-то. Если вы используете Amazon RDS, Heroku или любое другое размещенное решение, вы вряд ли сможете просто писать на чужой сервер.
Кен Киндер

459
$ mysql your_database --password=foo < my_requests.sql > out.csv

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

... .sql | sed 's/\t/,/g' > out.csv

5
не только это, но и позволяет создавать контент с удаленного хоста базы данных, в отличие от записи в локальную файловую систему.
tmarthal

31
Это табуляция, а не запятая.
Flimm

13
@Flimm, при условии, что у вас нет встроенных запятых / табуляций в полях, вы можете преобразовать их, отправив результат в| sed 's/\t/,/g'
Джон Картер

111
sed 'fix' не компенсирует запятые, которые могут появляться в любых из выбранных данных, и будет искажать выводимые столбцы соответствующим образом
Joey T

14
Негатив действителен ... он может сработать для вас сейчас, но вполне может укусить вас в будущем, когда ваши данные будут содержать табуляцию или запятую и т. Д.
Джон Хант

204

mysql --batch, -B

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

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


12
это предпочтительное решение: 1) списки значений, разделенных табуляцией, распространены в UNIX 2) импорт TSV изначально поддерживается большинством систем импорта, включая Excel, таблицы OpenOffice и т. д. 3) нет необходимости экранировать символы кавычек для текстовых полей 4 ) облегчает экспорт из командной строки
Joey T

5
это лучшее решение, потому что, в отличие от первого, не нужно иметь разрешения на таких серверах, как RDS
Muayyad Alsadi

8
Полезный трюк: если вы сохраните файл с разделителями табуляции как .xls вместо .csv, он откроется в Excel без необходимости преобразования текста в данные и без проблем с региональными настройками.
Сербаут

3
@Joey T - вам все еще нужно избегать вкладок и возврата каретки. Также, если содержимое поля выглядит как поле в кавычках или как экранированное, импортированный контент может не выглядеть как оригинал.
13

2
у вас будут проблемы с NULL .. они будут выглядеть как строковые нули ..
Jonathan

141

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

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

3
Флаг -e был именно тем, что я искал! Спасибо!
Гаурав Гупта

1
Это регулярное выражение довольно просто; как и многие другие ответы на этой странице, он просто очищает вывод mysql -B. Если вы разделите регулярное выражение на отдельные операторы в отдельных строках, это будет довольно просто (для тех, кто знает регулярное выражение) понять.
Мэй

7
На первый взгляд это выглядит довольно разбито. Вкладки и возврат каретки в содержании будут неправильно обработаны. "s / '/ \' /;" вообще ничего не делает, потому что двойные кавычки в команде shell используют обратную косую черту. Многие другие подобные ошибки с обратной косой чертой были потеряны. Нет обработки обратной косой черты в поле БД.
13

1
Похоже, эта команда хорошо работает в Linux, но не в Mac
Hemerson Varela

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

93

Только для Unix / Cygwin , передайте через 'tr':

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

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


53

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

--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


4
Если я что-то не пропустил, это создает файл TSV, а не файл CSV ...
PressingOnAlways

@PressingOnAlways Да. Цитата документа MySQL: «Печать результатов с использованием табуляции в качестве разделителя столбцов, с каждой строкой в ​​новой строке». Но разбор не должен быть проблемой с любым разделителем. Я использовал его для создания файлов Excel для моего клиента.
hrvoj3e

39

OUTFILE решение , данное Полем Tomblin вызывает файл , который будет записан на самой MySQL сервера, так что это будет работать только если у вас есть ФАЙЛА доступ, а также доступ входа в систему или другие средства для извлечения файла из этого окна.

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


36

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


2
Спасибо миллион Дэвид. Потратив 3 часа на то, чтобы новые строки правильно выводили содержимое HTML в данных, я использовал MySQL Workbench, и через 2 минуты у меня был готов файл CSV.
г-н евро

Я только что обнаружил, что он может сохранить как XML, и это здорово. Я надеюсь перейти с одного приложения на другое, используя XSLT для преобразования этого XML-файла в файл CSV, подходящий для импорта в целевое приложение.
Дэвид Оливер

mysql workbench - лучший вариант для функции импорта и экспорта.
Cijagani

1
Я только что успешно экспортировал более полумиллиона строк, используя инструментальные средства mysql, поэтому большие файлы не кажутся проблемой. Вам просто нужно убедиться, что вы удалили предел выбора перед выполнением запроса, и вам также может потребоваться увеличить следующие значения в вашем файле my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
Vincent

3
MySQL Workbench имеет неловкую утечку памяти при экспорте данных в CSV, если у вас большой набор данных, например, 1 или 2 миллиона строк, 12 ГБ ОЗУ (протестировано на моей машине с Linux) недостаточно, и память не очищается, если вы убить или остановить это. Для большого набора данных это не решение.
Остико

33

Как насчет:

mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv

2
Мне действительно нравится этот. Это намного чище, и мне нравится использование awk. Тем не менее, я бы, наверное, пошел с этим: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
Джош

7
Это не работает для значений полей с пробелами.
Барун Шарма

29

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

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, но я бы предпочел не поддерживать это для такой простой цели.

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


1
Вы правы, для сложных строк в таблице вы должны использовать приличную библиотеку, а не только bash. Я думаю, что у nodejs есть лучшие решения для такого рода действий. как этот пример
Yeya

1
Привет, хороший ответ, я хотел бы добавить ссылку на решение Python, предложенное ниже stackoverflow.com/a/35123787/1504300 , которое работает хорошо и очень просто. Я пытался отредактировать ваше сообщение, но редактирование было отклонено
действительно,

26

Многие из ответов на этой странице являются слабыми, потому что они не обрабатывают общий случай того, что может происходить в формате 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.

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


8
Еще более надежным решением было бы на самом деле подключиться к базе данных с помощью Python, тогда вам будет проще делать то, что вам нужно, для работы с большими наборами данных (разбиение результатов на части, потоковая передача и т. Д.).
Джош Рамбут

@JoshRumbut, очень поздно, но я сделал stackoverflow.com/a/41840534/2958070, чтобы дополнить ваш комментарий
Бен


17
  1. логика:

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

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


1
Приятно, так как это правильно без каких-либо дополнительных настроек.
Андрей Шульман

13

В этом ответе используется Python и популярная сторонняя библиотека PyMySQL . Я добавляю его, потому что библиотека csv в Python достаточно мощная, чтобы правильно обрабатывать различные варианты, .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
# /programming/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
Александр Балтасар

4
@AlexanderBaltasar, верно, и это выглядит полезным, но он не использует код Python для взаимодействия с базой данных. Смотрите комментарий по этому вопросу.
Бен

11

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

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, ...)

Это оно!


1
Обратите внимание, что NULLзначения будут пропущены concat_ws(), что приведет к несоответствию столбца. Чтобы избежать этого, просто используйте вместо этого пустую строку: IFNULL(field, '')(или все, что вы используете для представления NULL)
Марко Рой

10

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

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


1
Каковы ограничения этого с точки зрения размера файла / записи / чтения / и т. Д.?
Зак Смит

8

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

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    

4
Чтобы преобразовать в CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon

7
Использование sed -e 's/\t/,/g'безопасно только в том случае, если вы уверены, что ваши данные не содержат запятых или вкладок.
ожидает

7

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

Это не круто, но это сработало за 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);

?>

1
Красиво, чисто и быстро работает - это отличное решение, если вы можете запустить PHP в этой среде!
Джон Фиала

7

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

$ echo "SELECT * FROM Table123" | mysql Database456 | tr "\t" ,


5

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

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
artfulrobot

5

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

tee foobar.txt
SELECT foo FROM bar;

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

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


Если вместо .txt используется расширение .csv, есть ли какие-либо проблемы с форматированием, о которых следует знать?
datalifenyc

@myidealab Проблемы с форматированием возникают из-за запятых и т. д., которые не экранируются. CSV - это простой текстовый формат, поэтому не возникает проблем с форматированием, если просто выгрузить расширение.
jkmartindale

3

Используя решение, опубликованное Тимом, я создал этот сценарий 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

Если у вас настроен 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

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

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;

2

Если вы получаете сообщение об ошибке, 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 посещаемости в OUTFILE 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' ОБЛАСТИ, ПРЕКРАЩАЕМЫЕ ',' ENCLOSED BY '' 'ЛИНИИ, ПРЕКРАЩАЕМЫЕ' \ n ';

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


1

Крошечный 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

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

#!/bin/bash
#
# export mysql data to CSV
#/programming/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

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

mycli db_name --csv -e "select * from flowers" > flowers.csv

1

Если вы получаете эту ошибку при попытке экспортировать файл

ОШИБКА 1290 (HY000): Сервер MySQL работает с параметром --secure-file-priv, поэтому он не может выполнить этот оператор

и вы не можете решить эту ошибку. Вы можете сделать одну вещь, просто запустив этот скрипт 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]})

Добро пожаловать в переполнение стека! Это не отвечает на вопрос. Пожалуйста, просмотрите stackoverflow.com/help/how-to-answer .
Стивенвейд

0

Если на используемой вами машине установлен 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 и text, в которых есть текст, содержащий символы новой строки. Эти поля правильно заключены в кавычки, и эти новые строки в них будут интерпретироваться читателем CSV как часть текста, а не разделители записей. Это то, что потом трудно исправить с помощью sed или около того.


1
Это далеко не излишне сложное дело, но это единственное решение, которое идет в направлении, которое, вероятно, будет правильным - хотя и с небольшой дополнительной работой. CSV сложнее, чем кажется на первый взгляд, и вы допустили множество ошибок. например, обратная косая черта в оригинале. Лучше использовать библиотеку, которая проработала все вопросы для записи в CSV.
13

@ mc0e Обычно вы либо удваиваете цитату, либо избегаете ее. Я решил удвоить цитату, поэтому мне не нужен escape-символ. Разное программное обеспечение имеет разные представления о деталях CSV. Например, LOAD DATA в MySQL действительно обрабатывает \ как escape-символ, тогда как Open Office Calc - нет. Когда я писал ответ, я экспортировал данные в электронную таблицу.
user7610

1
Мой код обрабатывает все, что было необходимо для экспорта моего набора данных в тот день;) Ваш ответ также является шагом в правильном направлении, но, как говорится в первом комментарии, он должен 1) подключиться к базе данных sql из сценария напрямую, как а также 2) использовать правильную библиотеку CSV.
user7610
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.