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

есть ли простой способ запустить запрос 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

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

28 ответов


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


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

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

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

mysql --batch, - B

печать результатов с помощью tab в качестве разделителя столбцов, с каждой строкой на новая линия. С этой опцией mysql не использует файл истории. Пакетный режим в табличный формат и экранирование особые символы. Экранирование может быть отключено с помощью режима raw; см. описание для параметра --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

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


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

Unix/Cygwin только, труба его через 'tr':

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

N. B.: Это не обрабатывает ни встроенные запятые, ни встроенные вкладки.


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

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


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

--batch

--raw

пример:

sudo mysql -udemo_user -p -h127.0.0.1 --port=3306 \
   --default-character-set=utf8 --database=demo_database \
   --batch --raw < /var/demo_sql_query.sql > /var/demo_csv_export.csv

Как насчет:

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

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


все решения здесь на сегодняшний день, кроме MySQL workbench one, неверны и вполне возможно небезопасны (т. е. проблемы безопасности) для по крайней мере некоторого возможного содержимого в 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, но я бы предпочел не утверждают, что для такой простой цели.

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


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

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-файл


  1. логика :

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

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


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

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


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

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    

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

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

from your_table where etc;

объяснение:

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

вот именно!


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

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


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

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


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

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.


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

tee foobar.txt
SELECT foo FROM bar;

вы можете отключить его с помощью notee.

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


здание на 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);

?>

этот ответ использует 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 isn't much better, but this is an example
# http://stackoverflow.com/questions/12461484/is-it-secure-to-store-passwords-as-environment-variables-rather-than-as-plain-t
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)

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

#!/bin/bash

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

DBNAME=
TABLE=
FNAME=..csv
MCOMM=

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

он создаст файл с именем:


попробуйте этот код:

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


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

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

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

"установки" mysql2csv via

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

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


Если на машине, которую вы используете, установлен 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 или так.


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

#!/bin/bash

#  = query to execute
#  = outfile
#  = mysql database name
#  = mysql username

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

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

MYSQL_DB=""
MYSQL_USER="root"

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

if [ ! -z "" ]; then
    MYSQL_USER=
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 "" | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > 
echo "Written to "

следующий скрипт 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='3[0;34m'
red='3[0;31m'
green='3[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='3[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=""
  local l_msg=""
  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=""
  # 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:  [-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 " Help" 1>&2
  echo "===========" 1>&2
  echo " exports a csv file from a mysql database optionally limiting to a list of tables" 1>&2
  echo "   example:  --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=""
  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 "
  case "" in
    # options without arguments
    -h|--help) usage;;
    -d|--database)     database="" ; shift ;;
    -t|--tables)       tables="" ; shift ;;
    -o|--output)       csvoutput="" ; shift ;;
    -u|--user)         user="" ; shift ;;
    -hs|--host)        host="" ; shift ;;
    -p|--password)     password="" ; shift ;;
    -gs|--get-schema)  option="getschema";; 
    (--) shift; break;;
    (-*) echo ": error - unrecognized option " 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

вы можете использовать команду ниже из вашего местоположения SQL:

"mysql-h(имя хоста/IP>) -u(имя пользователя) -p(пароль) databasename outputFILE(.формат txt./XLS) и"

Эл.г хоста -х.х.х.х

uname-имя пользователя

password-пароль

DBName-employeeDB

запроса файл - работника.в SQL

выходной_файл - выходной_файл.в XLS

mysql-hx.X. X. x-uusername-ppassword employeeDB outputFile.в XLS

убедитесь, что вы выполняете команду из каталога, где находится SQL, или укажите полный путь к местоположению sql в приведенной выше команде.