Como gerar resultados da consulta MySQL no formato CSV?

1183

Existe uma maneira fácil de executar uma consulta MySQL na linha de comando do Linux e gerar os resultados no formato CSV ?

Aqui está o que estou fazendo agora:

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

Fica confuso quando há muitas colunas que precisam estar entre aspas ou se há aspas nos resultados que precisam ser escapadas.

MCS
fonte
1
Você pode usar REPLACE()em sua consulta para que as aspas não sejam exibidas.
dsm
Olhe para a minha resposta [neste stackoverflow] [1] [1]: stackoverflow.com/questions/12242772/...
Biniam
2
A resposta aceita a esta pergunta stackoverflow é provavelmente a melhor maneira: stackoverflow.com/questions/3760631/mysql-delimiter-question
Samuel Åslund
Eu escrevi uma solicitação de recurso no rastreador de erros do MariaDB ( jira.mariadb.org/browse/MDEV-12879 ) Você pode votar nela.
Jared Beck

Respostas:

1760

De 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';

Usando este comando, os nomes das colunas não serão exportados.

Observe também que /var/lib/mysql-files/orders.csvestará no servidor que está executando o MySQL. O usuário sob o qual o processo MySQL está executando deve ter permissão para gravar no diretório escolhido, ou o comando falhará.

Se você deseja gravar a saída em sua máquina local a partir de um servidor remoto (especialmente uma máquina hospedada ou virtualizada, como Heroku ou Amazon RDS), esta solução não é adequada.

Paul Tomblin
fonte
16
@ Tomas, se você tiver acesso a um sistema de arquivos remoto e MySQL, deverá poder escrever em algum lugar. em vez de / tmp, tente /home/yourusername/file.csv - se isso falhar e o conjunto de resultados não for tão grande, você poderá copiar a saída do seu cliente SSH e colar na máquina local.
Michael Butler
63
A pergunta especificava o MySQL, não "compatível com os padrões".
Paul Tomblin
35
Como incluir cabeçalho também?
Bogdan Gusiev
66
@BogdanGusiev, você pode incluir o cabeçalho adicionando "SELECT 'order_id', 'product_name', 'qty' UNION" antes da consulta real. A primeira consulta de seleção retorna o cabeçalho, a segunda consulta retorna dados reais; UNIÃO une-se.
petrkotek
19
@ Michael Butler: Bem, não, na verdade. Se você estiver usando o Amazon RDS, Heroku ou qualquer outra solução hospedada, é improvável que você consiga apenas gravar no servidor de outra pessoa.
Ken Kinder
459
$ mysql your_database --password=foo < my_requests.sql > out.csv

Qual é a tabulação separada. Canalize assim para obter um verdadeiro CSV (obrigado @therefromhere):

... .sql | sed 's/\t/,/g' > out.csv
Stan
fonte
5
não apenas isso, mas permite que o conteúdo seja criado a partir de um host de banco de dados remoto, diferente do outro ao gravar no sistema de arquivos local.
22411 TJMG #
31
É separado por tabulação, não por vírgula.
Flimm
13
@Flimm, supondo que você não tem vírgulas incorporadas / guias nos campos que você pode convertê-lo, canalizando o resultado em| sed 's/\t/,/g'
John Carter
111
a 'correção' sed não compensa vírgulas que possam aparecer em qualquer um dos dados selecionados e distorcerá as colunas produzidas de acordo.
Joey T
14
A negatividade é válido .. ele pode trabalhar para você agora, mas bem poderia mordê-lo no futuro, quando os seus dados inclui um guia ou uma vírgula etc ..
John Hunt
204

mysql --batch, -B

Imprima os resultados usando a guia como separador de colunas, com cada linha em uma nova linha. Com esta opção, o mysql não usa o arquivo histórico. O modo de lote resulta em formato de saída não tabular e escape de caracteres especiais. O escape pode ser desativado usando o modo bruto; veja a descrição para a opção --raw.

Isso fornecerá um arquivo separado por tabulação. Como vírgulas (ou cadeias que contêm vírgula) não são escapadas, não é fácil alterar o delimitador para vírgula.

serbaut
fonte
12
esta é uma solução preferida: 1) listas de valores separados por tabulação são comuns no UNIX 2) as importações de TSV são suportadas nativamente pela maioria dos sistemas de importação, incluindo Excel, planilhas do OpenOffice, etc. 3) não há necessidade de escapar de caracteres de aspas para os campos de texto ) torna as exportações de linha de comando uma brisa
Joey T
5
esta é a melhor solução porque ao contrário de primeira necessidade não tem permissões em servidores como RDS
Muayyad Alsadi
8
Um truque interessante: se você salvar o arquivo separado por tabulação como .xls em vez de .csv, ele será aberto no Excel sem a necessidade de conversão de "texto em dados" e sem problemas de configurações regionais.
serbaut
3
@ Joey T - você ainda precisa escapar de guias e retornos de carro. Além disso, se o conteúdo de um campo se parecer com um campo entre aspas ou de escape, o conteúdo importado poderá não ser o original.
Mc0e 10/10
2
você vai ter um problema com nulos .. eles vão sair como nulos cordas ..
Jonathan
141

Aqui está uma maneira bastante complicada de fazê-lo. Encontrei em algum lugar, não posso receber nenhum crédito

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

Funciona muito bem. Mais uma vez, apesar de uma regex provar apenas gravação.


Regex Explicação:

  • s /// significa substituir o que está entre o primeiro // pelo que está entre o segundo //
  • o "g" no final é um modificador que significa "toda instância, não apenas primeiro"
  • ^ (neste contexto) significa início da linha
  • $ (neste contexto) significa o fim da linha

Então, juntando tudo:

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
Tim Harding
fonte
3
A bandeira -e era exatamente o que eu estava procurando! Obrigado!
Gaurav Gupta
1
Este regex é bastante simples, na verdade; como muitas outras respostas nesta página, está apenas limpando a saída do mysql -B. Se você separasse a regex em instruções individuais em linhas separadas, seria bastante simples (para alguém que conhece regex) entender.
Mei
7
À primeira vista, isso parece bastante quebrado. Guias e retornos de carro no conteúdo serão manipulados incorretamente. "s / '/ \' /;" não faz nada, porque as aspas duplas no comando shell consomem a barra invertida. Muitos outros erros semelhantes com a barra invertida sendo perdida. Nenhuma manipulação para barra invertida no campo db.
Mc0e 10/10
1
Parece que este comando funciona bem em Linux, mas não no Mac
Hemerson Varela
6
Isso será interrompido se você tiver um campo de texto que contenha guias, barras invertidas ","e várias outras coisas. A regex é não a maneira de resolver este problema
Aidan
93

Somente Unix / Cygwin , passe através de 'tr':

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

Nota: trata-se nem de vírgulas incorporadas nem de separadores incorporados.

strickli
fonte
53

Isso me salvou algumas vezes. Rápido e funciona!

- lote Imprima os resultados usando a guia como separador de colunas, com cada linha em uma nova linha.

--raw desativa o escape de caracteres (\ n, \ t, \ 0 e \)

Exemplo:

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

Para completar, você pode converter para csv (mas tenha cuidado porque as guias podem estar dentro dos valores dos campos - por exemplo, campos de texto)

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

hrvoj3e
fonte
4
A menos que eu estou faltando alguma coisa, isso cria um arquivo TSV, não um arquivo CSV ...
PressingOnAlways
@PressingOnAlways Sim. Citação de documento do MySQL: "Imprima resultados usando tab como separador de colunas, com cada linha em uma nova linha." Mas a análise não deve ser um problema com nenhum delimitador. Eu usei para criar arquivos excel para o meu cliente.
Hrvoj3e
39

A solução OUTFILE fornecida por Paul Tomblin faz com que um arquivo seja gravado no próprio servidor MySQL, portanto, isso funcionará apenas se você tiver acesso FILE , bem como acesso de login ou outros meios para recuperar o arquivo dessa caixa.

Se você não tiver esse acesso, e a saída delimitada por tabulações for um substituto razoável para o CSV (por exemplo, se seu objetivo final for importar para o Excel), a solução da Serbaut (usando mysql --batche opcionalmente --raw) é o caminho a seguir.

Leland Woodbury
fonte
36

O MySQL Workbench pode exportar conjuntos de registros para CSV, e parece manipular vírgulas nos campos muito bem. O CSV é aberto no OpenOffice bem.

David Oliver
fonte
2
Obrigado, um milhão de David. Depois de passar 3 horas fazendo com que as novas linhas produzissem corretamente o conteúdo HTML nos dados, usei o MySQL Workbench e em 2 minutos tinha meu arquivo CSV pronto.
mr-euro
Acabei de descobrir que ele também pode salvar como XML, o que é ótimo. Espero migrar de um aplicativo para outro usando o XSLT para transformar esse XML em um arquivo CSV adequado para importação no aplicativo de destino.
David Oliver
O mysql workbench é a melhor opção para o recurso de exportação e importação.
cijagani
1
Acabei de exportar com sucesso mais de meio milhão de linhas usando o mysql workbench para que arquivos grandes não pareçam ser um problema. Você só precisa remover o limite de seleção antes de executar sua consulta e também pode aumentar os seguintes valores no seu arquivo my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
Vincent
3
O ambiente de trabalho MySQL possui um vazamento de memória embaraçoso ao exportar dados em CSV; se você tiver um conjunto de dados grande como 1 ou 2 milhões de linhas a mais, 12 GB de RAM (testado na minha máquina Linux) não serão suficientes e a memória não será limpa, a menos que você mate ou pare. Para grandes conjuntos de dados, isso não é uma solução.
Ostico
33

E se:

mysql your_database -p < my_requests.sql | awk '{print $1","$2}' > out.csv
Steve
fonte
2
Eu realmente gosto deste. É muito mais limpo, e eu gosto do uso do awk. No entanto, eu provavelmente teria concordado com isso: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
Josh
7
Isso falha para valores de campo com espaços.
Barun Sharma
29

Todas as soluções aqui atualizadas, exceto a do MySQL, estão incorretas e possivelmente inseguras (ou seja, problemas de segurança) para pelo menos algum conteúdo possível no banco de dados mysql.

O MYSQL Workbench (e o PHPMyAdmin da mesma forma) fornecem uma solução formalmente correta, mas foram projetados para baixar a saída no local do usuário. Eles não são tão úteis para automatizar a exportação de dados.

Não é possível gerar csv correto e confiável a partir da saída mysql -B -e 'SELECT ...'porque isso não pode codificar retornos de carro e espaço em branco nos campos. O sinalizador '-s' para o mysql faz escape de barra invertida e pode levar a uma solução correta. No entanto, o uso de uma linguagem de script (uma com estruturas de dados internas decentes que não sejam o bash) e bibliotecas nas quais os problemas de codificação já foram cuidadosamente trabalhados é muito mais seguro.

Pensei em escrever um script para isso, mas assim que pensei sobre o que eu chamaria, ocorreu-me procurar um trabalho preexistente com o mesmo nome. Embora eu não tenha examinado completamente, a solução em https://github.com/robmiller/mysql2csv parece promissora. Dependendo do seu aplicativo, a abordagem do yaml para especificar os comandos SQL pode ou não ser atraente. Também não estou entusiasmado com a exigência de uma versão mais recente do ruby ​​do que o padrão no meu laptop Ubuntu 12.04 ou nos servidores Debian Squeeze. Sim, eu sei que poderia usar o RVM, mas prefiro não manter isso com um objetivo tão simples.

Espero que alguém aponte uma ferramenta adequada, que tenha sido testada um pouco. Caso contrário, provavelmente atualizarei isso quando encontrar ou escrever um.

mc0e
fonte
1
Você está certo, para cadeias complexas na tabela, você precisa usar uma biblioteca decente, não apenas o bash. Eu acho que o nodejs tem melhores soluções para esse tipo de ação. como este exemplo
yeya 28/07
1
Olá, boa resposta, gostaria de adicionar um link para a solução python proposta abaixo stackoverflow.com/a/35123787/1504300 , que funciona bem e é muito simples. Eu tentei editar sua postagem, mas a edição foi rejeitada
reallynice
26

Muitas das respostas nesta página são fracas porque não tratam do caso geral do que pode ocorrer no formato CSV. por exemplo, vírgulas e aspas incorporadas em campos e outras condições que sempre surgem eventualmente. Precisamos de uma solução geral que funcione para todos os dados de entrada CSV válidos.

Aqui está uma solução simples e forte em 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)

Nomeie esse arquivo tab2csv, coloque-o no seu caminho, conceda permissões de execução e use-o assim:

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

As funções de manipulação de CSV do Python cobrem casos de canto para formatos de entrada CSV.

Isso poderia ser aprimorado para lidar com arquivos muito grandes por meio de uma abordagem de streaming.

Chris Johnson
fonte
8
Uma solução ainda mais confiável seria realmente conectar-se ao banco de dados com o Python, para facilitar o processo de lidar com conjuntos de dados maiores (resultados de chunking, streaming, etc.).
Josh Rumbut
@JoshRumbut, muito tarde, mas eu fiz stackoverflow.com/a/41840534/2958070 para complementar o seu comentário
Ben
24

Na sua linha de comando, você pode fazer isso:

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*

Créditos: Exportando tabela do Amazon RDS para um arquivo csv

Sri Murthy Upadhyayula
fonte
esse é um delineador louco. hatsoff
Elias Escalante
17
  1. lógica:

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

Quando você cria uma tabela CSV, o servidor cria um arquivo de formato de tabela no diretório do banco de dados. O arquivo começa com o nome da tabela e possui uma extensão .frm. O mecanismo de armazenamento também cria um arquivo de dados. Seu nome começa com o nome da tabela e possui uma extensão .CSV. O arquivo de dados é um arquivo de texto sem formatação. Quando você armazena dados na tabela, o mecanismo de armazenamento os salva no arquivo de dados no formato de valores separados por vírgula.

zloctb
fonte
1
Bom, pois isso está correto sem nenhum outro ajuste necessário.
Andrew Schulman
13

Esta resposta usa Python e uma popular biblioteca de terceiros, PyMySQL . Estou adicionando porque a biblioteca csv do Python é poderosa o suficiente para lidar corretamente com muitos tipos diferentes .csve nenhuma outra resposta está usando o código Python para interagir com o banco de dados.

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)
Ben
fonte
Uma resposta usando python já foi fornecida. stackoverflow.com/a/35123787/5470883
Alexander Baltasar
4
@AlexanderBaltasar, à direita, e parece útil, mas não está usando o código Python para interagir com o banco de dados. Veja o comentário sobre essa questão.
Ben
11

Isso é simples e funciona em qualquer coisa sem a necessidade de modo em lote ou arquivos de saída:

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

from your_table where etc;

Explicação:

  1. Substitua "por ""em cada campo ->replace(field1, '"', '""')
  2. Coloque cada resultado entre aspas -> concat('"', result1, '"')
  3. Coloque uma vírgula entre cada resultado citado -> concat_ws(',', quoted1, quoted2, ...)

É isso aí!

Marty Hirsch
fonte
1
Observe que os NULLvalores serão ignorados concat_ws(), resultando em uma incompatibilidade de coluna. Para evitar isso, basta usar uma string vazia: IFNULL(field, '')(ou qualquer outra coisa que você use para representar NULL) #
2133 Marco Roy
10

Como alternativa à resposta acima, você pode ter uma tabela MySQL que usa o mecanismo CSV.

Então você terá um arquivo no disco rígido que sempre estará em um formato CSV que você pode copiar sem processá-lo.

Jonathan
fonte
1
Quais são os limites disso em termos de tamanho do arquivo / gravações / leituras / etc?
Zach Smith
8

Para expandir as respostas anteriores, o one-liner a seguir exporta uma única tabela como um arquivo separado por tabulação. É adequado para automação, exportando o banco de dados todos os dias aproximadamente.

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

Convenientemente, podemos usar a mesma técnica para listar as tabelas do MySQL e descrever os campos em uma única tabela:

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    
johntellsall
fonte
4
Para converter para CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon
7
O uso sed -e 's/\t/,/g'é seguro apenas se você tiver certeza de que seus dados não contêm vírgulas ou guias.
awatts
7

Com base no user7610, aqui está a melhor maneira de fazer isso. Com mysql outfilehouve 60 minutos de problemas de propriedade e substituição de arquivos.

Não é legal, mas funcionou em 5 minutos.

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

?>
Michael Cole
fonte
1
Bom, limpo e funciona rapidamente - esta é uma ótima solução se você pode executar o PHP nesse ambiente!
John Fiala
7

Além disso, se você estiver executando a consulta na linha de comando do Bash, acredito que o trcomando possa ser usado para substituir as guias padrão por delimitadores arbitrários.

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

Brian
fonte
5

Aqui está o que eu faço:

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

O script perl (sniped de outro lugar) faz um bom trabalho de conversão dos campos espaçados por tabulação para CSV.

extraplanetário
fonte
Isso é ótimo. Ligeira melhoria poderia ser a de citar tudo, exceto os números perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F '- o seu não citaria1.2.3
artfulrobot
5

Não exatamente como um formato CSV, mas o teecomando do cliente MySQL pode ser usado para salvar a saída em um arquivo local :

tee foobar.txt
SELECT foo FROM bar;

Você pode desativá-lo usando notee.

O problema SELECT … INTO OUTFILE …;é que ele requer permissão para gravar arquivos no servidor.

Denilson Sá Maia
fonte
Se a extensão .csv for usada em vez de .txt, há algum problema de formatação a ser observado?
Datalifenyc
@myidealab Os problemas de formatação surgem de vírgulas, etc. O CSV é um formato de texto sem formatação, portanto, não há problema de formatação apenas com a troca da extensão.
Jkmartindale
3

Usando a solução postada por Tim, criei esse script bash para facilitar o processo (a senha root é solicitada, mas você pode modificar o script facilmente para solicitar qualquer outro usuário):

#!/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

Ele criará um arquivo chamado: database.table.csv

lepe
fonte
3

Se você tiver o PHP configurado no servidor, poderá usar o mysql2csv para exportar um arquivo CSV (realmente válido) para uma consulta mysql abitrar. Veja minha resposta no MySQL - SELECT * IN OUTFILE LOCAL? para um pouco mais de contexto / informação.

Tentei manter os nomes das opções, mysqlportanto, deve ser suficiente fornecer as opções --filee --query:

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

"Instalar" mysql2csvvia

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

(faça o download do conteúdo da lista principal, verifique a soma de verificação e torne-a executável).

Hirnhamster
fonte
3

O que funcionou para mim:

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

Nenhuma das soluções neste segmento funcionou para o meu caso em particular, eu tinha dados json bastante dentro de uma das colunas, que seriam confusas na minha saída csv. Para quem tem um problema semelhante, tente as linhas terminadas por \ r \ n.

Além disso, outro problema para quem tenta abrir o csv com o Microsoft Excel, lembre-se de que existe um limite de 32.767 caracteres que uma única célula pode conter, acima do que transborda para as linhas abaixo. Para identificar quais registros em uma coluna têm o problema, use a consulta abaixo. Em seguida, você pode truncar esses registros ou manipulá-los como desejar.

SELECT id,name,CHAR_LENGTH(json_student_description) AS 'character length'
FROM students
WHERE CHAR_LENGTH(json_student_description)>32767;
Rohit Chemburkar
fonte
2

Se você estiver recebendo um erro secure-file-priv, também, depois de mudar o local do arquivo de destino para dentro C:\ProgramData\MySQL\MySQL Server 8.0\Uploadse também depois da consulta

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

não está funcionando, basta alterar \(backsplash) da consulta para /(forwardsplash)

E isso funciona !!

Exemplo:

SELECT * DA participação no OUTFILE 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' CAMPOS TERMINADOS POR ',' FECHADO POR '"' LINHAS TERMINADAS POR '\ n';

Cada vez que você executa a consulta bem-sucedida, ela gera o novo arquivo csv a cada vez! Legal certo?

AAYUSH SHAH
fonte
1

Minúsculo script bash para fazer consultas simples a dumps CSV, inspirado em 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"
minitauros
fonte
1

O seguinte script bash funciona para mim. Opcionalmente, também obtém o esquema para as tabelas solicitadas.

#!/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
Wolfgang Fahl
fonte
1

Encontrei o mesmo problema e a resposta de Paulo não era uma opção, pois era o RDS. A substituição da guia pelas vírgulas não funcionou, pois os dados tinham vírgulas e guias incorporadas. Eu descobri que o mycli, que é uma alternativa drop-in para o cliente mysql, suporta saída csv fora da caixa com a --csvbandeira

mycli db_name --csv -e "select * from flowers" > flowers.csv
Shenal Silva
fonte
1

Se você estiver recebendo esse erro ao tentar exportar seu arquivo

ERRO 1290 (HY000): O servidor MySQL está sendo executado com a opção --secure-file-priv, portanto não pode executar esta instrução

e você não consegue resolver esse erro. Você pode fazer uma coisa simplesmente executando este script 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]})
Pranav
fonte
Bem-vindo ao Stack Overflow! Isso não responde à pergunta. Revise stackoverflow.com/help/how-to-answer .
stephenwade 4/04
0

Se houver PHP instalado na máquina que você está usando, você pode escrever um script PHP para fazer isso. Requer que a instalação do PHP tenha a extensão MySQL instalada.

Você pode chamar o interpretador PHP a partir da linha de comando da seguinte maneira:

php --php-ini path/to/php.ini your-script.php

Estou incluindo o --php-iniswitch, porque você pode precisar usar sua própria configuração de PHP que permite a extensão MySQL. No PHP 5.3.0+, essa extensão é ativada por padrão, de modo que não é mais necessário usar a configuração para ativá-la.

Então você pode escrever seu script de exportação como qualquer script PHP normal:

<?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";
    }
?>

A vantagem desse método é que ele não tem problemas com os campos varchar e texto, que possuem texto contendo novas linhas. Esses campos são citados corretamente e essas novas linhas serão interpretadas pelo leitor CSV como parte do texto, não como separadores de registros. Isso é algo que é difícil de corrigir depois com o sed ou algo assim.

user7610
fonte
1
Longe de ser desnecessariamente complicada, esta é a única solução aqui que segue uma direção que provavelmente será correta - embora com um pouco mais de trabalho. O CSV é mais complexo do que parece, e você cometeu vários erros. por exemplo, barras invertidas no original. Melhor usar uma biblioteca que tenha resolvido todos os problemas para gravar em CSV.
Mc0e 10/10
@ mc0e Normalmente, você duplica a cotação ou escapa da cotação. Decidi dobrar a citação, portanto não preciso de um caractere de escape. Software diferente tem idéias diferentes sobre detalhes de CSV. Por exemplo, LOAD DATA no MySQL trata \ como caractere de escape, enquanto o Open Office Calc não. Quando escrevi a resposta, estava exportando dados para uma planilha.
user7610
1
Meu código lida com tudo o que era necessário para exportar meu conjunto de dados de volta no dia;) Sua resposta também é uma etapa na direção correta, mas como o primeiro comentário diz, ele deve 1) conectar-se ao banco de dados sql a partir do script diretamente como bem como 2) use uma biblioteca csv adequada.
user7610