¿Cómo generar resultados de consultas MySQL en formato CSV?

¿Existe una manera fácil de ejecutar una consulta MySQL desde la línea de comandos de Linux y generar los resultados en CSV formato?

Esto es lo que estoy haciendo ahora:

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

Se vuelve complicado cuando hay muchas columnas que deben estar rodeadas de comillas, o si hay comillas en los resultados que deben escaparse.

preguntado el 10 de diciembre de 08 a las 13:12

Puede usar el REPLACE() en su consulta para que se escapen las comillas. -

Mira mi respuesta en [este stackoverflow] [1] [1]: stackoverflow.com/questions/12242772/… -

La respuesta aceptada a esta pregunta de stackoverflow es probablemente la mejor manera: stackoverflow.com/questions/3760631/mysql-delimiter-question -

Escribí una solicitud de función en el rastreador de errores MariaDB (jira.mariadb.org/browse/MDEV-12879) Puedes votarlo. -

30 Respuestas

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

Con este comando, los nombres de las columnas no se exportarán.

También tenga en cuenta que /var/lib/mysql-files/orders.csv estará en el servidor que está ejecutando MySQL. El usuario bajo el que se ejecuta el proceso MySQL debe tener permisos para escribir en el directorio elegido, o el comando fallará.

Si desea escribir la salida en su máquina local desde un servidor remoto (especialmente una máquina alojada o virtualizada como Heroku o Amazon RDS), esta solución no es adecuada.

Respondido 12 Oct 17, 20:10

@Tomas, si tiene acceso a un sistema de archivos remoto y MySQL, debe poder escribir en algún lugar. en lugar de / tmp, intente /home/yourusername/file.csv; si eso falla y el conjunto de resultados no es tan grande, puede copiar la salida de su cliente SSH y pegarla en su máquina local. - Michael Butler

La pregunta especificaba MySQL, no "compatible con los estándares". - pablo tomblin

¿Cómo incluir el encabezado también? - Bogdan Gusiev

@BogdanGusiev, puede incluir el encabezado anteponiendo "SELECT 'order_id', 'product_name', 'qty' UNION" antes de la consulta real. La primera consulta de selección devuelve el encabezado, la segunda consulta devuelve datos reales; UNION lo une. - petrkotek

@Michael Butler: Bueno, no, en realidad. Si está utilizando Amazon RDS, Heroku o cualquier otra solución alojada, es poco probable que pueda escribir en el servidor de otra persona. - ken kinder

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

Que está separado por tabuladores. Póngalo así para obtener un verdadero CSV (gracias @therefromhere):

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

Respondido 17 Oct 12, 18:10

no solo eso, sino que permite crear contenido desde un host de base de datos remoto, a diferencia de lo que ocurre con la escritura en el sistema de archivos local. - marthal

Está separado por tabuladores, no por comas. - flim

@Flimm, asumiendo que no tiene comas / pestañas incrustadas en los campos, puede convertirlo canalizando el resultado en | sed 's/\t/,/g' - John Carter

el sed 'fix' no compensa las comas que pueden aparecer en cualquiera de los datos seleccionados y sesgará las columnas generadas en consecuencia - joey t

La negatividad es válida ... podría funcionar para usted ahora, pero podría morderlo en el futuro cuando sus datos incluyan una pestaña o una coma, etc. Juan caza

mysql - lote, -B

Imprima los resultados usando la pestaña como separador de columnas, con cada fila en una nueva línea. Con esta opción, mysql no usa el archivo histórico. El modo por lotes da como resultado un formato de salida no tabular y el escape de caracteres especiales. El escape puede desactivarse utilizando el modo sin formato; consulte la descripción de la opción --raw.

Esto le dará un archivo separado por pestañas. Dado que las comas (o cadenas que contienen comas) no se escapan, no es sencillo cambiar el delimitador a coma.

Respondido el 30 de Septiembre de 09 a las 11:09

esta es una solución preferida: 1) las listas de valores separados por tabulaciones son comunes en UNIX 2) Las importaciones de TSV son compatibles de forma nativa con la mayoría de los sistemas de importación, incluidos Excel, OpenOffice Spreadsheets, etc. 3) no es necesario escapar los caracteres de comillas para los campos de texto 4 ) hace que las exportaciones de la línea de comandos sean muy sencillas - joey t

esta es la mejor solución porque, a diferencia de la primera, no es necesario tener permisos en servidores como RDS - Muayyad Alsadi

Un buen truco: si guarda el archivo separado por tabulaciones como .xls en lugar de .csv, se abrirá en Excel sin necesidad de conversión de "texto a datos" y sin problemas de configuración regional. - serbaut

@Joey T: aún necesita escapar de las pestañas y los retornos de carro. Además, si el contenido de un campo parece un campo entre comillas o de escape, es posible que el contenido importado no se parezca al original. - mc0e

tendrá un problema con los NULL ... saldrán como cadenas nulas .. - Jonathan

Aquí hay una forma bastante retorcida de hacerlo. Lo encontré en alguna parte, no puedo tomar ningún 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 bastante bien. Una vez más, aunque una expresión regular demuestra que solo se escribe.


Explicación de expresiones regulares:

  • s /// significa sustituir lo que está entre el primero // con lo que está entre el segundo //
  • la "g" al final es un modificador que significa "todas las instancias, no solo la primera"
  • ^ (en este contexto) significa comienzo de línea
  • $ (en este contexto) significa fin de línea

Entonces, poniéndolo todo junto:

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

contestado el 03 de mayo de 12 a las 18:05

¡La bandera -e era exactamente lo que estaba buscando! ¡Gracias! - Gaurav Gupta

Esta expresión regular es bastante simple en realidad; como muchas otras respuestas en esta página, solo está limpiando la salida de mysql -B. Si separa la expresión regular en declaraciones individuales en líneas separadas, sería bastante simple (para alguien que sepa expresiones regulares) de entender. - Mayo

A primera vista, esto parece bastante roto. Las pestañas y los retornos de carro en el contenido se manejarán incorrectamente. "s/'/\'/;" no hace nada en absoluto, porque las comillas dobles en el comando de shell consumen la barra invertida. Muchos otros errores similares con la barra invertida se pierden. No se maneja la barra invertida en el campo db. - mc0e

Parece que este comando funciona bien en Linux pero no en Mac. hemerson varela

Esto se romperá si tiene un campo de texto que contiene pestañas, barras invertidas, ","y muchas otras cosas. Una expresión regular es no la forma de resolver este problema - Aidan

Unix /Cygwin solo, canalícelo a través de 'tr':

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

NB: esto no maneja comas incrustadas ni pestañas incrustadas

respondido 02 nov., 15:12

Esto me salvó un par de veces. ¡Rápido y funciona!

--lote Imprimir resultados usando lengüeta como separador de columnas, con cada fila en una nueva línea.

--crudo inhabilita el escape de caracteres (\ n, \ t, \ 0 y \)

Ejemplo:

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, podrías convertir a csv (pero ten cuidado porque las pestañas podrían estar dentro de los valores de los campos, por ejemplo, campos de texto)

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

Respondido 16 Abr '19, 11:04

A menos que me falte algo, esto crea un archivo TSV, no un archivo CSV ... - PresionandoOnSiempre

@PressingOnAlways Sí. Cita del documento de MySQL: "Imprime los resultados usando la pestaña como separador de columnas, con cada fila en una nueva línea". Pero el análisis no debería ser un problema con ningún delimitador. Lo usé para hacer archivos de Excel para mi cliente. - hrvoj3e

La solución OUTFILE proporcionada por Paul Tomblin hace que se escriba un archivo en el servidor MySQL, por lo que esto funcionará solo si tiene ARCHIVO acceso, así como acceso de inicio de sesión u otros medios para recuperar el archivo de ese cuadro.

Si no tiene dicho acceso, y la salida delimitada por tabulaciones es un sustituto razonable de CSV (por ejemplo, si su objetivo final es importar a Excel), entonces la solución de Serbaut (usando mysql --batch y opcionalmente --raw) es el camino a seguir.

Respondido el 22 de junio de 10 a las 14:06

MySQL Workbench puede exportar conjuntos de registros a CSV, y parece manejar muy bien las comas en los campos. El CSV se abre en OpenOffice bien.

Respondido 28 ago 18, 16:08

Un millón de gracias David. Después de pasar 3 horas logrando que las líneas nuevas se generen correctamente para el contenido HTML en los datos, usé MySQL Workbench y en 2 minutos tenía mi archivo CSV listo. - señor-euro

Acabo de descubrir que también se puede guardar como XML, lo cual es genial. Espero migrar de una aplicación a otra utilizando XSLT para transformar este XML en un archivo CSV adecuado para importar a la aplicación de destino. - David Oliver

mysql workbench es la mejor opción para la función de importación y exportación. - cijagani

Acabo de exportar con éxito más de medio millón de filas usando mysql workbench, por lo que los archivos grandes no parecen ser un problema. Solo debe asegurarse de eliminar el límite de selección antes de ejecutar su consulta y es posible que también deba aumentar los siguientes valores en su archivo my.ini: max_allowed_packet = 500M, net_read_timeout = 600, net_write_timeout = 600 - Vincent

MySQL workbench tiene una pérdida de memoria embarazosa cuando exporta datos en CSV, si tiene un conjunto de datos grande como 1 o 2 millones de filas más, 12 GB de RAM (probados en mi máquina Linux) no son suficientes y la memoria no se borra a menos que usted matarlo o detenerlo. Para un gran conjunto de datos, esta no es una solución. - Ostico

Qué tal si:

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

contestado el 13 de mayo de 13 a las 12:05

Realmente me gusta esta. Es mucho más limpio y me gusta el uso de awk. Sin embargo, probablemente me hubiera ido con esto: mysql -uUser -pPassword your_database < my_requests.sql | awk 'BEGIN{OFS="=";} {print $1,$2}' > out.csv - Josh

Esto falla para los valores de campo con espacios. - Barun Sharma

Todas las soluciones aquí hasta la fecha, excepto la del banco de trabajo MySQL, son incorrectas y posiblemente inseguras (es decir, problemas de seguridad) para al menos parte del contenido posible en la base de datos mysql.

MYSQL Workbench (y de manera similar PHPMyAdmin) proporcionan una solución formalmente correcta, pero están diseñados para descargar la salida a la ubicación de un usuario. No son tan útiles para cosas como la automatización de la exportación de datos.

No es posible generar un csv correcto y confiable a partir de la salida de mysql -B -e 'SELECT ...' porque eso no puede codificar retornos de carro y espacios en blanco en los campos. La bandera '-s' de mysql hace un escape de barra invertida y podría conducir a una solución correcta. Sin embargo, usar un lenguaje de scripting (uno con estructuras de datos internas decentes, no bash) y bibliotecas donde los problemas de codificación ya se han resuelto cuidadosamente es mucho más seguro.

Pensé en escribir un guión para esto, pero tan pronto como pensé en cómo lo llamaría, se me ocurrió buscar un trabajo preexistente con el mismo nombre. Aunque no lo he repasado a fondo, la solución en https://github.com/robmiller/mysql2csv parece prometedor. Sin embargo, dependiendo de su aplicación, el enfoque yaml para especificar los comandos SQL puede resultar atractivo o no. Tampoco estoy encantado con el requisito de una versión más reciente de ruby ​​que la que viene de serie con mi computadora portátil Ubuntu 12.04 o los servidores Debian Squeeze. Sí, sé que podría usar RVM, pero prefiero no mantener eso para un propósito tan simple.

Con suerte, alguien señalará una herramienta adecuada, que ha sido probada un poco. De lo contrario, probablemente actualizaré esto cuando encuentre o escriba uno.

respondido 04 mar '19, 00:03

Tiene razón, para cadenas complejas en la tabla debe usar una biblioteca decente, no solo bash. Creo que nodejs tiene mejores soluciones para este tipo de acciones. como esto ejemplo -

Hola, buena respuesta, agregaría un enlace a la solución de Python propuesta a continuación stackoverflow.com/a/35123787/1504300, que funciona bien y es muy simple. Intenté editar tu publicación, pero la edición fue rechazada. muy agradable

El script mysql2csv de Rob Miller insiste en conectarse a la base de datos en sí, ya sea a través de una red o un socket, y no se puede usar como una tubería de estilo Unix. Tal vez sea necesario, pero realmente limita el uso. - cristianmtown

@chrisinmtown, ¿qué le gustaría agregar? ¿Salida de myslqldump tal vez? Como he señalado, la salida de mysql -Bno se puede arreglar. - mc0e

@ mc0e quiero canalizar in la salida de mysqldump, léalo como stdin. - cristianmtown

Muchas de las respuestas en esta página son débiles porque no manejan el caso general de lo que puede ocurrir en formato CSV. por ejemplo, comas y comillas incrustadas en campos y otras condiciones que siempre surgen eventualmente. Necesitamos una solución general que funcione para todos los datos de entrada CSV válidos.

Aquí hay una solución simple y sólida en 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)

Nombra ese archivo tab2csv, ponlo en tu ruta, dale permisos de ejecución, luego úsalo así:

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

Las funciones de manejo de CSV de Python cubren casos de esquina para los formatos de entrada CSV.

Esto podría mejorarse para manejar archivos muy grandes mediante un enfoque de transmisión.

Respondido el 12 de junio de 19 a las 22:06

Una solución aún más confiable sería conectarse realmente a la base de datos con Python, entonces debería ser más fácil hacer lo que necesita hacer para lidiar con conjuntos de datos más grandes (fragmentación de resultados, transmisión, etc.). - jose rumbut

@JoshRumbut, muy tarde, pero hice stackoverflow.com/a/41840534/2958070 para complementar tu comentario - paquet

Por favor mira stackoverflow.com/questions/356578/… para una versión extendida de este script con un dialecto de entrada que maneja comas incrustadas y comillas dobles - cristianmtown

Desde su línea de comando, puede hacer esto:

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: Exportación de una tabla de Amazon RDS a un archivo csv

contestado el 23 de mayo de 17 a las 13:05

ese es un delineador loco. felicitaciones - Elías Escalante

  1. lógica:

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

Cuando crea una tabla CSV, el servidor crea un archivo de formato de tabla en el directorio de la base de datos. El archivo comienza con el nombre de la tabla y tiene una extensión .frm. El motor de almacenamiento también crea un archivo de datos. Su nombre comienza con el nombre de la tabla y tiene una extensión .CSV. El archivo de datos es un archivo de texto sin formato. Cuando almacena datos en la tabla, el motor de almacenamiento los guarda en el archivo de datos en formato de valores separados por comas.

contestado el 07 de mayo de 14 a las 09:05

Agradable ya que esto es correcto sin ningún otro ajuste necesario. - Andrés Schulman

Esta respuesta usa Python y una biblioteca de terceros popular, PyMySQL. Lo estoy agregando porque Python's csv biblioteca es lo suficientemente potente como para correctamente manejar muchos sabores diferentes de .csv y ninguna otra respuesta utiliza código Python para interactuar con la base de datos.

import contextlib
import csv
import datetime
import os

# https://github.com/PyMySQL/PyMySQL
import pymysql

SQL_QUERY = """
SELECT * FROM my_table WHERE my_attribute = 'my_attribute';
"""

# embedding passwords in code gets nasty when you use version control
# the environment is not much better, but this is an example
# https://stackoverflow.com/questions/12461484
SQL_USER = os.environ['SQL_USER']
SQL_PASS = os.environ['SQL_PASS']

connection = pymysql.connect(host='localhost',
                             user=SQL_USER,
                             password=SQL_PASS,
                             db='dbname')

with contextlib.closing(connection):
    with connection.cursor() as cursor:
        cursor.execute(SQL_QUERY)
        # Hope you have enough memory :)
        results = cursor.fetchall()

output_file = 'my_query-{}.csv'.format(datetime.datetime.today().strftime('%Y-%m-%d'))
with open(output_file, 'w', newline='') as csvfile:
    # http://stackoverflow.com/a/17725590/2958070 about lineterminator
    csv_writer = csv.writer(csvfile, lineterminator='\n')
    csv_writer.writerows(results)

Respondido el 12 de junio de 19 a las 22:06

Ya se proporcionó una respuesta usando Python. stackoverflow.com/a/35123787/5470883 - Alejandro Baltasar

@AlexanderBaltasar, correcto, y parece útil, pero no usa código Python para interactuar con la base de datos. Vea el comentario sobre eso en esa pregunta. - paquet

Esto es simple y funciona en cualquier cosa sin necesidad de modo por lotes o archivos de salida:

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

from your_table where etc;

Explicación:

  1. Replace " con "" en cada campo -> replace(field1, '"', '""')
  2. Rodee cada resultado entre comillas -> concat('"', result1, '"')
  3. Coloque una coma entre cada resultado citado -> concat_ws(',', quoted1, quoted2, ...)

¡Eso es!

Respondido el 12 de junio de 19 a las 22:06

Tenga en cuenta que NULL los valores serán saltados por concat_ws(), lo que da como resultado una discrepancia de columna. Para evitar esto, simplemente use una cadena vacía en su lugar: IFNULL(field, '') (o cualquier otra cosa que uses para representar NULL) - marco roy

Además, si está realizando la consulta en la línea de comando de Bash, creo que tr El comando se puede utilizar para sustituir las pestañas predeterminadas por delimitadores arbitrarios.

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

respondido 19 nov., 20:23

Alternativamente a la respuesta anterior, puede tener una tabla MySQL que use el motor CSV.

Luego, tendrá un archivo en su disco duro que siempre estará en formato CSV y podrá copiarlo sin procesarlo.

Respondido el 10 de diciembre de 08 a las 23:12

¿Cuáles son los límites de esto en términos de tamaño de archivo / escrituras / lecturas / etc.? - zach smith

Encontré el mismo problema y Respuesta de Paul no era una opción ya que era RDS. Reemplazar la pestaña con las comas no funcionó porque los datos tenían comas y pestañas incrustadas. Encontré que el micli que es una alternativa para mysql-client admite salida csv lista para usar con el --csv bandera

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

Respondido 16 Feb 20, 10:02

Funciona a las mil maravillas, puedes instalar mycli en macOS a través de: brew update && brew install mycli. Nunca volveré a usar el cliente stock mysql, ¡mycli es tan legítimo! - bithavoc

Mycli y su primo pgcli son fantásticos. Vine aquí para agregar este consejo mysql porque no estaba llegando a ninguna parte con las otras soluciones. La salida limpia a un .csv local es sorprendentemente difícil con mysql. - cirujano

Impresionante, es muy triste que esta respuesta tenga muy pocos "me gusta". Es la única solución que se adapta a mis necesidades. Todos los demás no funcionaron perfectamente para mí, excepto esto. Tenía saltos de línea en las columnas, y eso condujo a nuevas líneas en el programa de Excel al abrir el archivo. - Esquife

Esta respuesta no funcionará si está atascado con la versión 1.8.1 (tal vez porque está usando un sistema operativo más antiguo que todavía tiene Python 2.x), ya que '--csv' no estaba disponible en esa versión. - José Van Riper

Para ampliar las respuestas anteriores, la siguiente línea única exporta una sola tabla como un archivo separado por tabulaciones. Es adecuado para la automatización, exportando la base de datos todos los días aproximadamente.

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

Convenientemente, podemos usar la misma técnica para enumerar las tablas de MySQL y describir los campos en una sola tabla:

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    

Respondido 23 Oct 14, 17:10

Para convertir a CSV: mysql -B -D mydatabase -e 'select * from mytable' | sed -e 's/\t/,/g' - DSimon

Usar sed -e 's/\t/,/g' solo es seguro si está seguro de que sus datos no contienen comas ni tabulaciones. - vatios

Sobre la base de user7610, esta es la mejor manera de hacerlo. Con mysql outfile Hubo 60 minutos de propiedad de archivos y problemas de sobrescritura.

No es genial, pero funcionó en 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);

?>

contestado el 29 de mayo de 15 a las 19:05

Agradable, limpio y funciona rápidamente: ¡esta es una gran solución si puede ejecutar PHP en ese entorno! - Juan Fiala

Esto es lo que hago:

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

El script de perl (sacado de otro lugar) hace un buen trabajo al convertir los campos espaciados por tabulaciones a CSV.

respondido 09 mar '12, 01:03

Esto es genial. Una ligera mejora podría ser citar todo excepto los números. perl -F"\t" -lane 'print join ",", map {s/"/""/g; /^\d+(?:\.\d+)?$/ ? $_ : qq("$_")} @F ' - el tuyo no citaría 1.2.3 - ingenioso

Esta debería ser la solución aceptada en mi humilde opinión, con la mejora de @ artfulrobot, por supuesto. - cristianmtown

No exactamente como formato CSV, pero tee comando de MySQL cliente se puede utilizar para guardar la salida en un locales archivo:

tee foobar.txt
SELECT foo FROM bar;

Puedes deshabilitarlo usando notee.

El problema con SELECT … INTO OUTFILE …; es que requiere permiso para escribir archivos en el servidor.

contestado el 29 de mayo de 14 a las 19:05

Si se usa la extensión .csv en lugar de .txt, ¿hay algún problema de formato que deba tener en cuenta? - datalifenyc

@myidealab Los problemas de formato surgen porque las comas, etc., no se escapan. CSV es un formato de texto sin formato, por lo que no hay problemas de formato solo por cambiar la extensión. - jkmartindale

Lo que funcionó para mí:

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

Ninguna de las soluciones en este hilo funcionó para mi caso particular, tenía bastante datos json dentro de una de las columnas, lo que se estropeaba en mi salida csv. Para aquellos con un problema similar, pruebe las líneas terminadas por \ r \ n en su lugar.

También otro problema para aquellos que intentan abrir el csv con Microsoft Excel, tenga en cuenta que hay un límite de 32,767 caracteres que puede contener una sola celda, por encima del cual se desborda a las filas de abajo. Para identificar qué registros de una columna tienen el problema, utilice la consulta a continuación. Luego puede truncar esos registros o manejarlos como desee.

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

respondido 07 nov., 18:06

Usando la solución publicada por Tim, creé este script bash para facilitar el proceso (se solicita la contraseña de root, pero puede modificar el script fácilmente para solicitar a cualquier otro usuario):

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

Creará un archivo llamado: base de datos.tabla.csv

contestado el 16 de mayo de 13 a las 09:05

¿qué pasa con los caracteres de comillas dobles incrustados? También necesitan escapar, pero no veo un patrón en el encantamiento sed para ellos. - cristianmtown

Si tiene PHP configurado en el servidor, puede usar mysql2csv para exportar un archivo CSV (realmente válido) para una consulta mysql abitraria. Ver mi respuesta en MySQL - SELECT * INTO OUTFILE LOCAL? para un poco más de contexto / información.

Traté de mantener los nombres de las opciones de mysql por lo que debería ser suficiente para proporcionar la --file y --query opciones:

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

"Instalar" mysql2csv vía

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

(descargue el contenido de la esencia, verifique la suma de comprobación y hágalo ejecutable).

contestado el 16 de mayo de 18 a las 12:05

Lo siguiente produce delimitado por tabulaciones y válido Salida CSV. A diferencia de la mayoría de las otras respuestas, esta técnica maneja correctamente el escape de pestañas, comas, comillas y nuevas líneas sin ningún filtro de flujo como sed, awk o tr. El ejemplo muestra cómo canalizar una tabla mysql remota directamente a una base de datos sqlite local usando streams. Esto funciona sin el permiso FILE o SELECT INTO OUTFILE. He agregado nuevas líneas para facilitar la lectura.

mysql -B -C --raw -u 'username' --password='password' --host='hostname' 'databasename'
-e 'SELECT
    CONCAT('\''"'\'',REPLACE(`id`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''id'\'',
    CONCAT('\''"'\'',REPLACE(`value`,'\''"'\'', '\''""'\''),'\''"'\'') AS '\''value'\''
    FROM sampledata'
2>/dev/null | sqlite3 -csv -separator $'\t' mydb.db '.import /dev/stdin mycsvtable'

El sistema 2>/dev/null es necesario para suprimir la advertencia sobre la contraseña en la línea de comando.

Si sus datos tienen NULL, puede usar la función IFNULL () en la consulta.

Respondido 17 Jul 19, 18:07

Si recibe un error de secure-file-priv luego, también después de cambiar la ubicación del archivo de destino dentro del C:\ProgramData\MySQL\MySQL Server 8.0\Uploads y también después de la 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';

no funciona, solo tienes que cambiar \(backsplash) de la consulta a / (salpicadura hacia adelante)

¡¡Y eso funciona !!

Ejemplo:

SELECCIONE * DE la asistencia a la SALIDA 'C: / ProgramData / MySQL / MySQL Server 8.0 / Uploads / FileName.csv' CAMPOS TERMINADOS POR ',' ENCERRADOS POR '"' LÍNEAS TERMINADAS POR '\ n';

¡Cada vez que ejecute la consulta exitosa, generará el nuevo archivo csv cada vez! ¿Guay, verdad?

Respondido el 20 de diciembre de 19 a las 15:12

Pequeño script bash para realizar consultas simples a volcados CSV, inspirado en 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"

respondido 01 mar '18, 12:03

Esto usa el encantamiento sed que ignora los caracteres de comillas dobles incrustados. Sugiera usar la solución de Perl en su lugar. - cristianmtown

El siguiente script de bash funciona para mí. Opcionalmente, también obtiene el esquema de las tablas solicitadas.

#!/bin/bash
#
# export mysql data to CSV
#https://stackoverflow.com/questions/356578/how-to-output-mysql-query-results-in-csv-format
#

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'
red='\033[0;31m'
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}


#
# error
#
# show the given error message on stderr and exit
#
#   params:
#     1: l_msg - the error message to display
#
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error:" 1>&2
  color_msg $red "\t$l_msg" 1>&2
  usage
}

#
# display usage 
#
usage() {
  echo "usage: $0 [-h|--help]" 1>&2
  echo "               -o  | --output      csvdirectory"    1>&2
  echo "               -d  | --database    database"   1>&2
  echo "               -t  | --tables      tables"     1>&2
  echo "               -p  | --password    password"   1>&2
  echo "               -u  | --user        user"       1>&2
  echo "               -hs | --host        host"       1>&2
  echo "               -gs | --get-schema"             1>&2
  echo "" 1>&2
  echo "     output: output csv directory to export mysql data into" 1>&2
  echo "" 1>&2
  echo "         user: mysql user" 1>&2
  echo "     password: mysql password" 1>&2
  echo "" 1>&2
  echo "     database: target database" 1>&2
  echo "       tables: tables to export" 1>&2
  echo "         host: host of target database" 1>&2
  echo "" 1>&2
  echo "  -h|--help: show help" 1>&2
  exit 1
}

#
# show help 
#
help() {
  echo "$0 Help" 1>&2
  echo "===========" 1>&2
  echo "$0 exports a csv file from a mysql database optionally limiting to a list of tables" 1>&2
  echo "   example: $0 --database=cms --user=scott --password=tiger  --tables=person --output person.csv" 1>&2
  echo "" 1>&2
  usage
}

domysql() {
  mysql --host $host -u$user --password=$password $database
}

getcolumns() {
  local l_table="$1"
  echo "describe $l_table" | domysql | cut -f1 | grep -v "Field" | grep -v "Warning" | paste -sd "," - 2>/dev/null
}

host="localhost"
mysqlfiles="/var/lib/mysql-files/"

# parse command line options
while true; do
  #echo "option $1"
  case "$1" in
    # options without arguments
    -h|--help) usage;;
    -d|--database)     database="$2" ; shift ;;
    -t|--tables)       tables="$2" ; shift ;;
    -o|--output)       csvoutput="$2" ; shift ;;
    -u|--user)         user="$2" ; shift ;;
    -hs|--host)        host="$2" ; shift ;;
    -p|--password)     password="$2" ; shift ;;
    -gs|--get-schema)  option="getschema";; 
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; usage;;
    (*) break;;
  esac
  shift
done

# checks
if [ "$csvoutput" == "" ]
then
  error "ouput csv directory not set"
fi
if [ "$database" == "" ]
then
  error "mysql database not set"
fi
if [ "$user" == "" ]
then
  error "mysql user not set"
fi
if [ "$password" == "" ]
then
  error "mysql password not set"
fi

color_msg $blue "exporting tables of database $database"
if [ "$tables" = "" ]
then
tables=$(echo "show tables" | domysql)
fi

case $option in
  getschema) 
   rm $csvoutput$database.schema
   for table in $tables
   do
     color_msg $blue "getting schema for $table"
     echo -n "$table:" >> $csvoutput$database.schema
     getcolumns $table >> $csvoutput$database.schema
   done  
   ;;
  *)
for table in $tables
do
  color_msg $blue "exporting table $table"
  cols=$(grep "$table:" $csvoutput$database.schema | cut -f2 -d:)
  if [  "$cols" = "" ]
  then
    cols=$(getcolumns $table)
  fi
  ssh $host rm $mysqlfiles/$table.csv
cat <<EOF | mysql --host $host -u$user --password=$password $database 
SELECT $cols FROM $table INTO OUTFILE '$mysqlfiles$table.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
EOF
  scp $host:$mysqlfiles/$table.csv $csvoutput$table.csv.raw
  (echo "$cols"; cat $csvoutput$table.csv.raw) > $csvoutput$table.csv
  rm $csvoutput$table.csv.raw
done
  ;;
esac

contestado el 14 de mayo de 18 a las 16:05

De pie sobre los hombros de @ChrisJohnson, extendí la respuesta de febrero de 2016 con un dialecto personalizado para leer. Esta herramienta de canalización de shell no necesita conectarse a su base de datos, maneja comas y comillas aleatorias en la entrada y funciona bien en Python2 y Python3!

#!/usr/bin/env python
import csv
import sys
# fields are separated by tabs; double-quotes may occur anywhere
csv.register_dialect("mysql", delimiter="\t", quoting=csv.QUOTE_NONE)
tab_in = csv.reader(sys.stdin, dialect="mysql")
comma_out = csv.writer(sys.stdout, dialect=csv.excel)
for row in tab_in:
    # print("row: {}".format(row))
    comma_out.writerow(row)

Use esa declaración impresa para convencerse de que está analizando su entrada correctamente :)

Una advertencia importante: tratamiento de los caracteres de retorno de carro, ^ M también conocido como control-M, \ r en términos de Linux. Aunque la salida de Mysql en modo por lotes escapa correctamente de los caracteres de nueva línea incrustados, por lo que realmente hay una fila por línea (definida por el carácter de nueva línea de linux \ n), mysql no pone comillas alrededor de los datos de la columna. Si un elemento de datos tiene un carácter de retorno de carro incrustado, csv.reader rechaza esa entrada con esta excepción:

new-line character seen in unquoted field - 
do you need to open the file in universal-newline mode?

Por favor, no @ yo diga que debería usar el modo de archivo universal volviendo a abrir sys.stdin.fileno con el modo 'rU'. Intenté eso, hace que los caracteres \ r incrustados se traten como marcadores de fin de registro, por lo que un solo registro de entrada se transforma incorrectamente en muchos registros de salida incompletos. No he encontrado una solución de Python para esta limitación del módulo csv.reader de Python. Creo que la causa raíz es la implementación / limitación de csv.reader que se indica en su documentación https://docs.python.org/3/library/csv.html#csv.reader:

The reader is hard-coded to recognise either '\r' or '\n' as end-of-line,
and ignores lineterminator.

La solución débil e insatisfactoria que puedo ofrecer es cambiar cada carácter \ r a la secuencia de dos caracteres '\ n' antes de que el csv.reader de Python vea los datos. Usé el comando sed. Aquí hay un ejemplo de una canalización con una selección de mysql y la secuencia de comandos de Python de arriba:

mysql -u user db --execute="select * from table where id=12345" \
  | sed -e 's/\r/\\n/g' \
  | mysqlTsvToCsv.py

Después de luchar contra esto durante algún tiempo, creo que Python no es la solución correcta. Si puede vivir con perl, creo que el script de una sola línea que ofrece @artfulrobot puede ser la solución más eficaz y sencilla.

Respondido el 25 de Septiembre de 20 a las 15:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.