Importar desde CSV
Importar datos desde archivos CSV es una de las operaciones más comunes al poblar tablas MySQL. Ya sea que recibas datos de un sistema externo, un archivo de Excel convertido a CSV, o necesites cargar datos de prueba, MySQL ofrece herramientas eficientes para realizar esta tarea. La sentencia LOAD DATA INFILE es la opción más rápida y la herramienta mysqlimport proporciona la misma funcionalidad desde la línea de comandos.
Sintaxis de LOAD DATA INFILE
La forma básica de LOAD DATA INFILE lee un archivo del servidor y lo carga en una tabla:
LOAD DATA INFILE '/var/lib/mysql-files/productos.csv'
INTO TABLE productos
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;La cláusula IGNORE 1 ROWS omite la primera fila del archivo, que normalmente contiene los encabezados de columna. Sin esta cláusula, MySQL intentaría insertar los nombres de las columnas como datos, lo que causaría errores de tipo.
LOAD DATA LOCAL INFILE
Si el archivo está en la máquina del cliente y no en el servidor, usa LOCAL:
LOAD DATA LOCAL INFILE '/home/usuario/datos/productos.csv'
INTO TABLE productos
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;La diferencia es que con LOCAL, el archivo se transfiere desde la máquina del cliente al servidor a través de la conexión MySQL. Sin LOCAL, el servidor lee el archivo directamente de su propio sistema de archivos.
Para que LOCAL funcione, debe estar habilitado tanto en el servidor como en el cliente:
-- Verificar si LOCAL INFILE está habilitado
SHOW VARIABLES LIKE 'local_infile';| Variable_name | Value |
|---|---|
| local_infile | OFF |
-- Habilitar en el servidor
SET GLOBAL local_infile = 1;Al conectar con el cliente mysql, usa la opción --local-infile:
mysql --local-infile -u root -p tienda_mysqlOpciones de formato de campos
Las opciones de campos y líneas deben coincidir exactamente con el formato del archivo CSV:
LOAD DATA INFILE '/var/lib/mysql-files/datos.csv'
INTO TABLE productos
FIELDS
TERMINATED BY ',' -- separador de campos
ENCLOSED BY '"' -- carácter que encierra valores de texto
ESCAPED BY '\\' -- carácter de escape
LINES
TERMINATED BY '\n' -- separador de líneas
STARTING BY '' -- prefijo de cada línea (vacío = ninguno)
IGNORE 1 ROWS;Para archivos con punto y coma como separador (formato europeo):
LOAD DATA INFILE '/var/lib/mysql-files/datos_eu.csv'
INTO TABLE productos
FIELDS TERMINATED BY ';'
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;Para archivos TSV (separados por tabulador):
LOAD DATA INFILE '/var/lib/mysql-files/datos.tsv'
INTO TABLE productos
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n';Mapear columnas del archivo a columnas de la tabla
Si el archivo CSV no tiene las columnas en el mismo orden que la tabla, o tiene columnas adicionales que quieres ignorar, especifica el mapeo explícitamente:
-- El archivo tiene: nombre, categoria, precio, descripcion
-- La tabla tiene: id (AUTO_INCREMENT), nombre, precio, stock, categoria_id
LOAD DATA INFILE '/var/lib/mysql-files/productos_import.csv'
INTO TABLE productos
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(nombre, @categoria, precio, @descripcion)
SET categoria_id = (SELECT id FROM categorias WHERE nombre = @categoria),
stock = 0;Las variables precedidas por @ son variables de usuario que capturan el valor del campo pero no lo insertan directamente. La cláusula SET permite transformar esos valores antes de insertarlos. En este ejemplo, el nombre de la categoría del CSV se busca en la tabla categorias para obtener su ID.
Transformar datos durante la importación
La cláusula SET permite realizar transformaciones complejas:
LOAD DATA INFILE '/var/lib/mysql-files/clientes.csv'
INTO TABLE clientes
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(nombre, @apellido, email, @fecha_str, @telefono)
SET
apellidos = UPPER(@apellido),
fecha_registro = STR_TO_DATE(@fecha_str, '%d/%m/%Y'),
telefono = IF(@telefono = '', NULL, @telefono);En este ejemplo, los apellidos se convierten a mayúsculas, la fecha se parsea desde formato europeo (DD/MM/YYYY), y los teléfonos vacíos se convierten en NULL.
Manejar errores y filas duplicadas
Por defecto, LOAD DATA INFILE se detiene ante el primer error. Puedes controlar este comportamiento:
-- Ignorar filas que causan errores (duplicados, tipos incompatibles)
LOAD DATA INFILE '/var/lib/mysql-files/productos.csv'
IGNORE
INTO TABLE productos
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;La palabra clave IGNORE después del nombre del archivo hace que MySQL omita silenciosamente las filas que violan restricciones de unicidad o tienen datos incompatibles.
Alternativamente, REPLACE elimina las filas existentes que conflictan y las reemplaza con las nuevas:
-- Reemplazar filas existentes
LOAD DATA INFILE '/var/lib/mysql-files/productos_actualizados.csv'
REPLACE
INTO TABLE productos
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;Después de la importación, verifica cuántas filas se cargaron y cuántas tuvieron problemas:
-- Ver advertencias de la última operación
SHOW WARNINGS;Rendimiento de la carga
LOAD DATA INFILE es significativamente más rápido que sentencias INSERT individuales porque procesa los datos en bloque y minimiza el overhead de parseo SQL.
Para maximizar el rendimiento en cargas grandes:
-- Desactivar verificaciones durante la carga
SET foreign_key_checks = 0;
SET unique_checks = 0;
SET autocommit = 0;
LOAD DATA INFILE '/var/lib/mysql-files/datos_masivos.csv'
INTO TABLE log_actividad
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
COMMIT;
-- Reactivar verificaciones
SET foreign_key_checks = 1;
SET unique_checks = 1;
SET autocommit = 1;Desactivar foreign_key_checks y unique_checks temporalmente elimina la verificación de restricciones fila por fila, lo que puede acelerar la carga en un orden de magnitud para tablas con múltiples índices.
mysqlimport
La herramienta mysqlimport proporciona la misma funcionalidad de LOAD DATA INFILE desde la línea de comandos:
mysqlimport --local \
--fields-terminated-by=',' \
--fields-enclosed-by='"' \
--lines-terminated-by='\n' \
--ignore-lines=1 \
-u root -p \
tienda_mysql /tmp/productos.csvUn detalle importante: mysqlimport determina la tabla destino a partir del nombre del archivo. Un archivo llamado productos.csv se importará en la tabla productos. Si necesitas importar a una tabla con un nombre diferente, renombra el archivo antes de la importación.
# Renombrar para importar en la tabla correcta
cp datos_export.csv productos.csv
mysqlimport --local --fields-terminated-by=',' \
-u root -p tienda_mysql productos.csvRestricción secure_file_priv
Al igual que con SELECT INTO OUTFILE, la variable secure_file_priv restringe desde qué directorio el servidor puede leer archivos:
SHOW VARIABLES LIKE 'secure_file_priv';Si está configurada, copia el archivo al directorio permitido antes de importar:
sudo cp /home/usuario/productos.csv /var/lib/mysql-files/
sudo chown mysql:mysql /var/lib/mysql-files/productos.csvLa alternativa es usar LOAD DATA LOCAL INFILE, que lee el archivo desde el cliente y no está sujeta a secure_file_priv.
Codificación de caracteres
Si el archivo CSV tiene una codificación diferente a la de tu base de datos:
LOAD DATA INFILE '/var/lib/mysql-files/datos_latin1.csv'
INTO TABLE productos
CHARACTER SET latin1
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;MySQL convertirá automáticamente los datos de latin1 a la codificación de la tabla (generalmente utf8mb4). Para archivos UTF-8 con BOM, puede ser necesario omitir los primeros bytes:
LOAD DATA INFILE '/var/lib/mysql-files/datos_utf8bom.csv'
INTO TABLE productos
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;Ejemplo completo práctico
Supongamos que recibes un archivo CSV de un proveedor con productos nuevos:
nombre,marca,precio_usd,stock,fecha_disponibilidad
"Monitor Ultra Wide 34",Samsung,549.99,120,15/03/2026
"Teclado mecánico RGB",Logitech,129.99,350,01/03/2026
"Ratón ergonómico",Microsoft,79.99,500,20/02/2026
LOAD DATA LOCAL INFILE '/home/admin/proveedor_marzo.csv'
INTO TABLE productos
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(@nombre, @marca, @precio_usd, stock, @fecha)
SET
nombre = @nombre,
precio = @precio_usd * 0.92,
fecha_disponible = STR_TO_DATE(@fecha, '%d/%m/%Y'),
marca_id = (SELECT id FROM marcas WHERE nombre = @marca);Este ejemplo transforma el precio de USD a EUR multiplicando por 0.92, convierte la fecha del formato europeo, y busca el ID de la marca por nombre.
Importar datos desde CSV con LOAD DATA INFILE es la forma más eficiente de cargar datos externos en MySQL. Para archivos pequeños o importaciones ocasionales, también puedes considerar herramientas como MySQL Workbench que ofrecen asistentes gráficos para la importación.
Escrito por Eduardo Lázaro
