Come produrre i risultati delle query MySQL in formato CSV?


1183

Esiste un modo semplice per eseguire una query MySQL dalla riga di comando di Linux e generare i risultati in formato CSV ?

Ecco cosa sto facendo ora:

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

Diventa disordinato quando ci sono molte colonne che devono essere racchiuse tra virgolette o se ci sono virgolette nei risultati che devono essere sfuggite.


1
È possibile utilizzare REPLACE()nella query per fare in modo che le virgolette vengano salvate.
dsm,

Guardate la mia risposta in [questo StackOverflow] [1] [1]: stackoverflow.com/questions/12242772/...
Biniam


2
La risposta accettata a questa domanda stackoverflow è probabilmente il modo migliore: stackoverflow.com/questions/3760631/mysql-delimiter-question
Samuel Åslund

Ho scritto una richiesta di funzione sul bug tracker MariaDB ( jira.mariadb.org/browse/MDEV-12879 ) Puoi votare su di esso.
Jared Beck,

Risposte:


1760

Da 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 questo comando i nomi delle colonne non verranno esportati.

Si noti inoltre che /var/lib/mysql-files/orders.csvsarà sul server che esegue MySQL. L'utente con cui è in esecuzione il processo MySQL deve disporre delle autorizzazioni per scrivere nella directory scelta, altrimenti il ​​comando fallirà.

Se si desidera scrivere output sul proprio computer locale da un server remoto (in particolare un computer ospitato o virtualizzare come Heroku o Amazon RDS), questa soluzione non è adatta.


16
@Tomas se hai accesso a un filesystem remoto e MySQL, devi essere in grado di scrivere da qualche parte. invece di / tmp, prova /home/yourusername/file.csv - se fallisce, e il set di risultati non è così grande, puoi copiare l'output dal tuo client SSH e incollarlo sul tuo computer locale.
Michael Butler,

63
La domanda specificava MySQL, non "conforme agli standard".
Paul Tomblin,

35
Come includere anche l'intestazione?
Bogdan Gusiev,

66
@BogdanGusiev, puoi includere l'intestazione anteponendo "SELECT 'order_id', 'product_name', 'qty' UNION" prima della vera query. La prima query selezionata restituisce l'intestazione, la seconda query restituisce dati reali; UNION lo unisce.
petrkotek,

19
@Michael Butler: Beh, no, in realtà. Se stai utilizzando Amazon RDS, Heroku o qualsiasi altra soluzione ospitata, è improbabile che tu sia in grado di scrivere sul server di qualcun altro.
Ken Kinder,

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

Quale è separato da tabulazione. Installa così per ottenere un vero CSV (grazie @therefromhere):

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

5
non solo, ma consente la creazione di contenuto da un host di database remoto, diversamente dall'altro della scrittura nel filesystem locale.
tmarthal,

31
È separato da tabulazioni, non separato da virgola.
Flimm,

13
@Flimm, supponendo che non ci siano virgole / tab incorporate nei campi, puoi convertirlo eseguendo il piping del risultato in| sed 's/\t/,/g'
John Carter,

111
la 'correzione' di sed non compensa le virgole che possono apparire in nessuno dei dati selezionati e inclinerà di conseguenza le colonne prodotte di conseguenza
Joey T

14
La negatività è valida .. potrebbe funzionare per te ora ma potrebbe anche morderti in futuro quando i tuoi dati includono una scheda o una virgola ecc.
John Hunt

204

mysql --batch, -B

Stampa i risultati utilizzando la scheda come separatore di colonna, con ogni riga su una nuova riga. Con questa opzione, mysql non utilizza il file cronologico. La modalità batch comporta un formato di output non tabulare e la escape di caratteri speciali. L'escaping può essere disabilitato usando la modalità raw; vedere la descrizione per l'opzione --raw.

Questo ti darà un file separato da tabulazioni. Poiché le virgole (o le stringhe contenenti virgola) non sono salvate, non è semplice modificare il delimitatore in virgola.


12
questa è una soluzione preferita: 1) gli elenchi di valori separati da tabulazione sono comuni in UNIX 2) Le importazioni TSV sono supportate in modo nativo dalla maggior parte dei sistemi di importazione, inclusi Excel, fogli di calcolo OpenOffice, ecc. 3) non è necessario sfuggire ai caratteri di citazione per i campi di testo 4 ) rende le esportazioni da riga di comando un gioco da ragazzi
Joey T

5
questa è la soluzione migliore perché a differenza della prima non è necessario disporre delle autorizzazioni per server come RDS
Muayyad Alsadi

8
Un trucco accurato: se salvi il file separato da tabulazioni come .xls anziché .csv, si aprirà in Excel senza la necessità di una conversione da "testo a dati" e senza problemi di impostazioni regionali.
serbaut,

3
@Joey T: devi ancora sfuggire alle schede e ai ritorni a capo. Inoltre, se il contenuto di un campo appare come un campo tra virgolette o con escape, il contenuto importato potrebbe non apparire come l'originale.
mc0e

2
avrai un problema con i NULL .. usciranno come string nulls ..
Jonathan

141

Ecco un modo abbastanza nodoso di farlo. Trovato da qualche parte, non posso prendermi il merito

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

Funziona abbastanza bene. Ancora una volta, però, una regex dimostra solo la scrittura.


Spiegazione Regex:

  • s /// significa sostituire ciò che è tra il primo // con ciò che è tra il secondo //
  • la "g" alla fine è un modificatore che significa "tutte le istanze, non solo le prime"
  • ^ (in questo contesto) significa l'inizio della riga
  • $ (in questo contesto) significa fine della riga

Quindi, mettendo tutto insieme:

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
La bandiera -e era esattamente quello che stavo cercando! Grazie!
Gaurav Gupta,

1
Questa regex è davvero molto semplice; come molte altre risposte in questa pagina, sta semplicemente ripulendo l'output di mysql -B. Se separassi la regex in singole istruzioni su righe separate, sarebbe abbastanza semplice (per qualcuno che conosce regex) capire.
Mei

7
A prima vista, sembra piuttosto rotto. Le schede e i ritorni a capo nel contenuto verranno gestiti in modo errato. "S/'/\'/;" non fa nulla, perché le doppie virgolette nel comando shell consumano la barra rovesciata. Molti altri bug simili con la barra rovesciata che si perde. Nessuna gestione per la barra rovesciata nel campo db.
mc0e

1
Sembra che questo comando
funzioni

6
Questo si interromperà se si dispone di un campo di testo che contiene schede, barre rovesciate ","e una serie di altre cose. Un regex non è il modo di risolvere questo problema
helpan

93

Solo Unix / Cygwin , instradalo attraverso 'tr':

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

NB: Questo non gestisce né virgole incorporate, né schede incorporate.


53

Questo mi ha salvato un paio di volte. Veloce e funziona!

--batch Stampa i risultati usando tab come separatore di colonna, con ogni riga su una nuova riga.

--raw disabilita l'escaping dei caratteri (\ n, \ t, \ 0 e \)

Esempio:

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

Per completezza potresti convertire in csv (ma fai attenzione perché le schede potrebbero trovarsi all'interno dei valori dei campi - ad es. Campi di testo)

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


4
A meno che non mi manchi qualcosa, questo crea un file TSV, non un file CSV ...
PressingOnAlways

@PressingOnSempre Sì. Citazione del documento MySQL: "Stampa i risultati usando tab come separatore di colonna, con ogni riga su una nuova riga". Ma l'analisi non dovrebbe essere un problema con alcun delimitatore. L'ho usato per creare file Excel per il mio client.
hrvoj3e,

39

La soluzione OUTFILE fornita da Paul Tomblin provoca la scrittura di un file sul server MySQL stesso, quindi funzionerà solo se si dispone dell'accesso FILE , nonché dell'accesso di accesso o di altri mezzi per recuperare il file da quella casella.

Se non si dispone di tale accesso e l'output delimitato da tabulazioni è un ragionevole sostituto di CSV (ad esempio, se l'obiettivo finale è importare in Excel), la soluzione di Serbaut (utilizzando mysql --batche facoltativamente --raw) è la strada da percorrere.


36

MySQL Workbench può esportare recordset in CSV e sembra gestire molto bene le virgole nei campi. Il CSV si apre in OpenOffice bene.


2
Grazie un milione di David. Dopo aver trascorso 3 ore a ottenere l'output corretto delle newline per il contenuto HTML nei dati, ho usato MySQL Workbench e in 2 minuti ho preparato il mio file CSV.
sig. Euro

Ho appena scoperto che può salvare anche come XML, il che è fantastico. Spero di migrare da un'applicazione all'altra utilizzando XSLT per trasformare questo XML in un file CSV adatto per l'importazione nell'applicazione di destinazione.
David Oliver,

mysql workbench è la migliore opzione per l'import export.
Cijagani,

1
Ho appena esportato con successo oltre mezzo milione di righe usando mysql workbench, quindi i file di grandi dimensioni non sembrano essere un problema. Devi solo assicurarti di rimuovere il limite di selezione prima di eseguire la query e potresti anche dover aumentare i seguenti valori nel tuo file my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600
Vincent

3
MySQL workbench ha una perdita di memoria imbarazzante quando si esportano dati in CSV, se si dispone di un set di dati di grandi dimensioni come 1 o 2 milioni di righe in più, 12 GB di RAM (testati sulla mia macchina Linux) non sono sufficienti e la memoria non viene cancellata a meno che non si uccidilo o fermalo. Per set di dati di grandi dimensioni questa non è una soluzione.
Ostico,

33

Che ne dite di:

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

2
Mi piace molto questo. È molto più pulito e mi piace l'uso di awk. Tuttavia, sarei probabilmente andato con questo: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv
Josh

7
Questo non riesce per i valori di campo con spazi.
Barun Sharma,

29

Tutte le soluzioni qui aggiornate, ad eccezione di quella di MySQL, sono errate e molto probabilmente non sicure (ad esempio problemi di sicurezza) per almeno alcuni possibili contenuti nel database mysql.

MYSQL Workbench (e similmente PHPMyAdmin) forniscono una soluzione formalmente corretta, ma sono progettati per scaricare l'output nella posizione dell'utente. Non sono così utili per cose come automatizzare l'esportazione dei dati.

Non è possibile generare csv in modo affidabile corretto dall'output di mysql -B -e 'SELECT ...'perché ciò non può codificare i ritorni a capo e lo spazio bianco nei campi. Il flag '-s' su mysql evita il backslash e potrebbe portare a una soluzione corretta. Tuttavia, l'uso di un linguaggio di scripting (uno con strutture dati interne decenti che non è bash) e librerie in cui i problemi di codifica sono già stati accuratamente elaborati è molto più sicuro.

Ho pensato di scrivere una sceneggiatura per questo, ma non appena ho pensato a come l'avrei chiamata, mi è venuto in mente di cercare un'opera preesistente con lo stesso nome. Anche se non l'ho esaminato a fondo, la soluzione su https://github.com/robmiller/mysql2csv sembra promettente. A seconda dell'applicazione, tuttavia, l'approccio yaml alla specifica dei comandi SQL potrebbe o meno fare appello. Inoltre, non sono entusiasta del requisito di una versione più recente di ruby ​​rispetto a quella standard del mio laptop Ubuntu 12.04 o dei server Debian Squeeze. Sì, lo so che potrei usare RVM, ma preferirei non mantenerlo per uno scopo così semplice.

Eventualmente qualcuno indicherà uno strumento adatto, che ha avuto un po 'di test. Altrimenti probabilmente lo aggiornerò quando ne troverò o scriverò uno.


1
Hai ragione, per stringhe complesse nella tabella devi usare una libreria decente, non solo bash. Penso che nodejs abbia soluzioni migliori per questo tipo di azioni. come in questo esempio
yeya,

1
Ciao, buona risposta, aggiungerei un link alla soluzione Python proposta sotto stackoverflow.com/a/35123787/1504300 , che funziona bene ed è molto semplice. Ho provato a modificare il tuo post ma la modifica è stata respinta
davvero, il

26

Molte delle risposte in questa pagina sono deboli perché non gestiscono il caso generale di ciò che può accadere in formato CSV. ad esempio virgole e virgolette incorporate in campi e altre condizioni che emergono sempre alla fine. Abbiamo bisogno di una soluzione generale che funzioni per tutti i dati di input CSV validi.

Ecco una soluzione semplice e potente in 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)

Assegna un nome al file tab2csv, inseriscilo nel tuo percorso, assegnagli le autorizzazioni di esecuzione, quindi utilizzalo in questo modo:

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

Le funzioni di gestione CSV di Python coprono casi angolari per i formati di input CSV.

Questo potrebbe essere migliorato per gestire file molto grandi tramite un approccio di streaming.


8
Una soluzione ancora più affidabile sarebbe quella di connettersi effettivamente al database con Python, quindi si dovrebbe avere più tempo a fare ciò che è necessario fare per gestire set di dati più grandi (risultati di chunking, streaming, ecc.).
Josh Rumbut,

@JoshRumbut, molto tardi, ma ho fatto stackoverflow.com/a/41840534/2958070 per integrare il tuo commento
Ben


17
  1. logica:

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

Quando si crea una tabella CSV, il server crea un file in formato tabella nella directory del database. Il file inizia con il nome della tabella e ha un'estensione .frm. Il motore di archiviazione crea anche un file di dati. Il suo nome inizia con il nome della tabella e ha un'estensione .CSV. Il file di dati è un file di testo semplice. Quando si archiviano i dati nella tabella, il motore di archiviazione li salva nel file di dati in formato valori separati da virgola.


1
Bello poiché questo è corretto senza altre regolazioni necessarie.
Andrew Schulman,

13

Questa risposta utilizza Python e una popolare libreria di terze parti, PyMySQL . Lo sto aggiungendo perché la libreria CSV di Python è abbastanza potente da gestire correttamente molti gusti diversi .csve nessuna altra risposta sta usando il codice Python per interagire con il database.

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)

Una risposta usando python era già stata fornita. stackoverflow.com/a/35123787/5470883
Alexander Baltasar il

4
@AlexanderBaltasar, giusto, e sembra utile, ma non sta usando il codice Python per interagire con il database. Vedi il commento su questo su quella domanda.
Ben

11

Questo è semplice e funziona su qualsiasi cosa senza la necessità di modalità batch o file di output:

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

from your_table where etc;

Spiegazione:

  1. Sostituisci "con ""in ogni campo ->replace(field1, '"', '""')
  2. Circondare ogni risultato tra virgolette -> concat('"', result1, '"')
  3. Inserire una virgola tra ogni risultato citato -> concat_ws(',', quoted1, quoted2, ...)

Questo è tutto!


1
Si noti che i NULLvalori verranno ignorati concat_ws(), causando una mancata corrispondenza della colonna. Per evitarlo, usa invece una stringa vuota: IFNULL(field, '')(o qualsiasi altra cosa usi per rappresentare NULL)
Marco Roy,

10

In alternativa alla risposta sopra, puoi avere una tabella MySQL che utilizza il motore CSV.

Quindi avrai un file sul tuo disco rigido che sarà sempre in un formato CSV che potresti semplicemente copiare senza elaborarlo.


1
Quali sono i limiti di ciò in termini di dimensioni del file / scritture / letture / ecc?
Zach Smith,

8

Per espandere le risposte precedenti, il seguente one-liner esporta una singola tabella come file separato da tabulazioni. È adatto per l'automazione, esportando il database ogni giorno o giù di lì.

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

Convenientemente, possiamo usare la stessa tecnica per elencare le tabelle di MySQL e per descrivere i campi su una singola tabella:

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
Per convertire in CSV:mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g'
DSimon

7
L'uso sed -e 's/\t/,/g'è sicuro solo se sei sicuro che i tuoi dati non contengano virgole o schede.
risveglia il

7

Sulla base di user7610, ecco il modo migliore per farlo. Con mysql outfilec'erano 60 minuti di proprietà dei file e problemi di sovrascrittura.

Non è bello, ma ha funzionato in 5 minuti.

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
Bello, pulito e funziona rapidamente: questa è un'ottima soluzione se puoi eseguire PHP in quell'ambiente!
John Fiala,

7

Inoltre, se stai eseguendo la query sulla riga di comando di Bash, credo che il trcomando possa essere utilizzato per sostituire le schede predefinite con delimitatori arbitrari.

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


5

Ecco cosa faccio:

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

Lo script perl (acquisito altrove) fa un buon lavoro nel convertire i campi distanziati da tabulazioni in CSV.


Questo è fantastico Un leggero miglioramento potrebbe essere quello di citare tutto tranne i numeri perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F '- il tuo non 1.2.3
citerebbe

5

Non esattamente come un formato CSV, ma il teecomando dal client MySQL può essere utilizzato per salvare l'output in un file locale :

tee foobar.txt
SELECT foo FROM bar;

Puoi disabilitarlo usando notee.

Il problema SELECT … INTO OUTFILE …;è che richiede l'autorizzazione per scrivere file sul server.


Se viene utilizzata l'estensione .csv invece di .txt, ci sono problemi di formattazione da tenere presente?
datalifenyc,

@myidealab I problemi di formattazione derivano da virgole ecc. che non vengono salvati. CSV è un formato di testo semplice, quindi non c'è problema di formattazione solo dallo scambio dell'estensione.
jkmartindale,

3

Usando la soluzione pubblicata da Tim, ho creato questo script bash per facilitare il processo (è richiesta la password di root, ma puoi modificare facilmente lo script per chiedere a qualsiasi altro utente):

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

Creerà un file chiamato: database.table.csv


3

Se hai PHP impostato sul server, puoi usare mysql2csv per esportare un file CSV (effettivamente valido) per una query mysql abitaria. Vedi la mia risposta su MySQL - SELEZIONA * IN OUTFILE LOCAL?per un po 'più di contesto / informazioni.

Ho provato a mantenere i nomi delle opzioni, mysqlquindi dovrebbe essere sufficiente fornire le opzioni --filee --query:

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

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

(scarica il contenuto dell'essenza, controlla il checksum e rendilo eseguibile).


3

Cosa ha funzionato per me:

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

Nessuna delle soluzioni su questo thread ha funzionato per il mio caso particolare, avevo dei dati piuttosto json all'interno di una delle colonne, che sarebbero stati incasinati nel mio output CSV. Per quelli con un problema simile, prova invece le linee terminate da \ r \ n.

Anche un altro problema per coloro che cercano di aprire il CSV con Microsoft Excel, tieni presente che esiste un limite di 32.767 caratteri che può contenere una singola cella, al di sopra del quale trabocca alle righe sottostanti. Per identificare quali record in una colonna presentano il problema, utilizzare la query seguente. Puoi quindi troncare quei record o gestirli come desideri.

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

2

Se si verifica un errore di secure-file-privallora, anche dopo aver spostato la posizione del file di destinazione all'interno C:\ProgramData\MySQL\MySQL Server 8.0\Uploadse anche dopo la query-

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

non funziona, devi solo cambiare \(backsplash) dalla query a /(forwardsplash)

E funziona così !!

Esempio:

SELEZIONA * DALLA PRESENTAZIONE IN OUTFILE 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' CAMPI TERMINATI DA ',' INCLUSO DA '"' LINEE TERMINATE DA '\ n';

Ogni volta che esegui la query corretta, genererà ogni volta il nuovo file CSV! Bene, vero?


1

Piccolo script bash per eseguire query semplici nei dump CSV, ispirato a 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

Il seguente script bash funziona per me. Opzionalmente ottiene anche lo schema per le tabelle richieste.

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

Ho riscontrato lo stesso problema e la risposta di Paul non era un'opzione poiché era RDS. La sostituzione della scheda con le virgole non ha funzionato poiché i dati avevano virgole e schede incorporate. Ho scoperto che il mycli che è un'alternativa drop-in per il client mysql supporta l'output CSV fuori dalla scatola con il --csvflag

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

1

Se ricevi questo errore mentre tenti di esportare il tuo file

ERRORE 1290 (HY000): il server MySQL è in esecuzione con l'opzione --secure-file-priv quindi non può eseguire questa istruzione

e non sei in grado di risolvere questo errore. Puoi fare una cosa semplicemente eseguendo questo 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]})

Benvenuto in Stack Overflow! Questo non risponde alla domanda. Si prega di rivedere stackoverflow.com/help/how-to-answer .
stephenwade,

0

Se sul computer in uso è installato PHP, è possibile scrivere uno script PHP per farlo. Richiede che l'installazione di PHP abbia l'estensione MySQL installata.

Puoi chiamare l'interprete PHP dalla riga di comando in questo modo:

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

Sto includendo il --php-ini switch, perché potrebbe essere necessario utilizzare la propria configurazione PHP che abilita l'estensione MySQL. Su PHP 5.3.0+ tale estensione è abilitata per impostazione predefinita, quindi non è più necessario utilizzare la configurazione per abilitarla.

Quindi puoi scrivere il tuo script di esportazione come qualsiasi normale script 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";
    }
?>

Il vantaggio di questo metodo è che non ha problemi con varchar e campi di testo che hanno testo contenente nuove righe. Quei campi sono correttamente citati e le nuove righe in essi contenute verranno interpretate dal lettore CSV come parte del testo, non come separatori di record. Questo è qualcosa che è difficile da correggere in seguito con sed o così.


1
Lungi dall'essere inutilmente complicata, questa è l'unica soluzione qui che va in una direzione probabilmente corretta - anche se con un po 'più di lavoro. Il CSV è più complesso di quanto sembri inizialmente e hai commesso diversi errori. ad esempio barre rovesciate nell'originale. Meglio usare una libreria che ha risolto tutti i problemi per scrivere su CSV.
mc0e

@ mc0e Solitamente raddoppi la citazione o sfuggi alla citazione. Ho deciso di raddoppiare la citazione, quindi non ho bisogno di un personaggio di escape. Software diverso ha idee diverse sui dettagli CSV. Ad esempio, LOAD DATA in MySQL tratta effettivamente \ come carattere di escape, mentre Open Office Calc no. Quando ho scritto la risposta stavo esportando i dati in un foglio di calcolo.
user7610

1
Il mio codice gestisce tutto ciò che era necessario per esportare il mio set di dati nel corso della giornata;) La tua risposta è anche un passo nella direzione corretta, ma come dice il primo commento, dovrebbe 1) connettersi al database sql dallo script direttamente come oltre a 2) utilizzare una libreria CSV adeguata.
user7610
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.