Exportar a CSV
Exportar datos de MySQL a formato CSV es una necesidad frecuente. Los archivos CSV son universales: los puedes abrir con Excel, importar en herramientas de análisis, cargar en otros sistemas o compartirlos con personas que no tienen acceso a la base de datos. MySQL ofrece varias formas de generar archivos CSV, desde la sentencia SELECT ... INTO OUTFILE hasta alternativas usando el cliente de línea de comandos.
Sintaxis de SELECT INTO OUTFILE
La forma nativa de MySQL para exportar a CSV es SELECT ... INTO OUTFILE:
SELECT *
INTO OUTFILE '/tmp/productos.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;Esta sentencia escribe el resultado de la consulta directamente a un archivo en el sistema de archivos del servidor. Cada fila de la tabla se convierte en una línea del archivo, con los campos separados por comas y los valores de texto entre comillas dobles.
Opciones de formato
Las cláusulas de formato controlan exactamente cómo se estructura el archivo CSV:
FIELDS TERMINATED BY define el separador entre campos. La coma es lo estándar para CSV, pero puedes usar tabulador ('\t'), punto y coma (';') u otro carácter según las necesidades del sistema destino.
ENCLOSED BY especifica el carácter que rodea los valores de texto. Las comillas dobles ('"') son lo más común. Si usas OPTIONALLY ENCLOSED BY, solo se encierran las columnas de tipo cadena, no las numéricas.
LINES TERMINATED BY define el separador de líneas. En Linux se usa '\n', en Windows '\r\n'.
ESCAPED BY define el carácter de escape para caracteres especiales dentro de los valores. Por defecto es la barra invertida ('\\').
-- CSV con punto y coma (común en Europa)
SELECT nombre, precio, stock
INTO OUTFILE '/tmp/productos_eu.csv'
FIELDS TERMINATED BY ';'
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;
-- TSV (valores separados por tabulador)
SELECT nombre, precio, stock
INTO OUTFILE '/tmp/productos.tsv'
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
FROM productos;Añadir encabezados de columna
SELECT INTO OUTFILE no incluye encabezados de columna por defecto. Puedes añadirlos con un UNION:
SELECT 'nombre', 'precio', 'stock', 'categoria'
UNION ALL
SELECT nombre, precio, stock, categoria_id
INTO OUTFILE '/tmp/productos_con_header.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;La primera parte del UNION genera una fila con los nombres de las columnas, y el UNION ALL la combina con los datos reales.
La restricción secure_file_priv
MySQL controla dónde pueden escribirse los archivos mediante la variable secure_file_priv:
SHOW VARIABLES LIKE 'secure_file_priv';| Variable_name | Value |
|---|---|
| secure_file_priv | /var/lib/mysql-files/ |
Si el valor no es vacío, solo puedes escribir archivos en ese directorio. Si intentas escribir en otro lugar, recibirás un error:
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option
Para exportar al directorio permitido:
SELECT nombre, precio, stock
INTO OUTFILE '/var/lib/mysql-files/productos.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;Luego puedes mover el archivo al destino deseado desde el sistema operativo:
sudo cp /var/lib/mysql-files/productos.csv /home/usuario/exportaciones/Exportar consultas complejas
No estás limitado a exportar tablas completas. Puedes exportar el resultado de cualquier consulta:
-- Exportar un resumen de ventas por categoría
SELECT
c.nombre AS categoria,
COUNT(dp.id) AS total_ventas,
SUM(dp.cantidad * dp.precio_unitario) AS ingresos
INTO OUTFILE '/var/lib/mysql-files/ventas_por_categoria.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM detalle_pedidos dp
JOIN productos p ON dp.producto_id = p.id
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY ingresos DESC;Alternativa con mysql -e y redirección
Si no puedes usar INTO OUTFILE por restricciones de secure_file_priv o porque necesitas generar el archivo en la máquina cliente (no en el servidor), usa el cliente mysql con redirección:
# Exportar con tabuladores (formato por defecto del cliente mysql)
mysql -u root -p -e "SELECT nombre, precio, stock FROM tienda_mysql.productos" > productos.tsv
# Convertir a CSV con comas
mysql -u root -p -N -B -e "SELECT nombre, precio, stock FROM tienda_mysql.productos" \
| sed 's/\t/,/g' > productos.csvLa opción -N omite los nombres de columna y -B activa el modo batch que no dibuja bordes de tabla.
Para incluir encabezados y obtener un CSV limpio:
# Con encabezados
mysql -u root -p -B -e "SELECT nombre, precio, stock FROM tienda_mysql.productos" \
| sed 's/\t/,/g' > productos.csvExportar con formato CSV limpio usando mysql --batch
Una combinación más robusta que maneja correctamente los valores con comas y saltos de línea:
mysql -u root -p --batch --raw -e "
SELECT
CONCAT('\"', REPLACE(nombre, '\"', '\"\"'), '\"') AS nombre,
precio,
stock
FROM tienda_mysql.productos
" | sed '1s/\t/,/g; 2,$s/\t/,/g' > productos.csvExportar tablas grandes
Para tablas con millones de filas, el archivo resultante puede ser muy grande. Comprime la salida directamente:
mysql -u root -p -N -B -e "SELECT * FROM tienda_mysql.log_actividad" \
| sed 's/\t/,/g' | gzip > log_actividad.csv.gzSi necesitas dividir el archivo en partes más manejables:
# Exportar y dividir en archivos de 100MB
mysql -u root -p -N -B -e "SELECT * FROM tienda_mysql.pedidos" \
| sed 's/\t/,/g' | split -b 100M - pedidos_parte_Caracteres especiales y codificación
Si tus datos contienen caracteres especiales, acentos u otros caracteres UTF-8, asegúrate de que la exportación mantiene la codificación correcta:
-- Establecer la codificación de la conexión antes de exportar
SET NAMES utf8mb4;
SELECT nombre, descripcion
INTO OUTFILE '/var/lib/mysql-files/productos_utf8.csv'
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;Con el cliente de línea de comandos:
mysql -u root -p --default-character-set=utf8mb4 -N -B \
-e "SELECT nombre, precio FROM tienda_mysql.productos" \
| sed 's/\t/,/g' > productos_utf8.csvValores NULL
En SELECT INTO OUTFILE, los valores NULL se exportan como \N por defecto. Si prefieres que aparezcan como cadena vacía o como la palabra "NULL":
SELECT
nombre,
IFNULL(descripcion, '') AS descripcion,
precio
INTO OUTFILE '/var/lib/mysql-files/productos_sin_null.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM productos;La función IFNULL reemplaza los NULL por el valor que especifiques antes de que se escriban en el archivo.
Exportar a CSV es una operación sencilla pero con matices importantes en cuanto a formato, codificación y ubicación del archivo. En el siguiente artículo veremos el proceso inverso: importar datos desde archivos CSV a MySQL.
Escrito por Eduardo Lázaro
