INSERT múltiples filas

MySQL permite insertar varias filas en una sola sentencia INSERT, separando cada grupo de valores con una coma. Es significativamente más rápido que ejecutar múltiples sentencias INSERT individuales, porque MySQL solo necesita analizar la sentencia una vez y puede optimizar la escritura en disco.

Sintaxis

INSERT INTO tabla (columna1, columna2, ...)
VALUES
    (valor1a, valor2a, ...),
    (valor1b, valor2b, ...),
    (valor1c, valor2c, ...);

Cada paréntesis define una fila completa. Todas las filas deben tener el mismo número de valores y corresponder a las columnas especificadas.

Insertar varias categorías

Añadir tres subcategorías de Deportes en una sola operación:

INSERT INTO categorias (nombre, descripcion, categoria_padre_id) VALUES
    ('Natación', 'Equipamiento para natación', 4),
    ('Ciclismo', 'Bicicletas y accesorios', 4),
    ('Yoga', 'Accesorios para yoga y meditación', 4);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

MySQL confirma que 3 filas fueron insertadas. Si una de las filas causara un error (por ejemplo, una restricción violada), ninguna se insertaría: la operación es atómica.

Insertar varios productos

Añadir productos a las nuevas categorías:

INSERT INTO productos (nombre, descripcion, precio, stock, categoria_id) VALUES
    ('iPad Air', 'Tablet Apple con chip M2 y pantalla Liquid Retina', 699.00, 30, 17),
    ('Samsung Galaxy Tab S9', 'Tablet Samsung con pantalla AMOLED', 549.00, 25, 17),
    ('Lenovo Tab P12', 'Tablet Lenovo de 12.7 pulgadas', 349.00, 40, 17);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

Las tres tablets se insertan de una vez. Las columnas id, activo, creado_en y actualizado_en reciben sus valores por defecto automáticamente.

Insertar clientes con datos parciales

No todas las filas necesitan los mismos valores opcionales, pero todas deben proporcionar las mismas columnas. Si algunas filas tienen NULL en ciertos campos, debes indicarlo explícitamente:

INSERT INTO clientes (nombre, apellidos, email, telefono, ciudad, codigo_postal) VALUES
    ('Raquel', 'Iglesias Pardo', 'raquel.iglesias@email.com', '612000001', 'Sevilla', '41001'),
    ('Tomás', 'Pardo Crespo', 'tomas.pardo@email.com', NULL, 'Valencia', '46001'),
    ('Marina', 'Crespo Ramos', 'marina.crespo@email.com', '634000002', 'Bilbao', '48001');

Tomás no tiene teléfono registrado (NULL). Al usar la inserción múltiple, todas las filas deben incluir la columna telefono, pero pueden pasar NULL como valor.

Rendimiento

La diferencia de rendimiento es notable. Insertar 1000 filas con un solo INSERT multi-fila puede ser 10 veces más rápido que 1000 sentencias INSERT individuales. Las razones son:

MySQL analiza la sentencia SQL una sola vez en lugar de 1000 veces. Se reduce drásticamente el overhead de comunicación entre el cliente y el servidor. MySQL puede agrupar las escrituras en disco de forma más eficiente. Los índices se actualizan de forma más óptima cuando se procesan múltiples filas juntas.

-- Lento: 1000 sentencias separadas
INSERT INTO productos (...) VALUES ('Producto 1', ...);
INSERT INTO productos (...) VALUES ('Producto 2', ...);
-- ... 998 más
 
-- Rápido: una sola sentencia
INSERT INTO productos (...) VALUES
    ('Producto 1', ...),
    ('Producto 2', ...),
    -- ... 998 más
    ('Producto 1000', ...);

LAST_INSERT_ID con múltiples filas

Cuando insertas varias filas a la vez, LAST_INSERT_ID() devuelve el ID de la primera fila insertada, no de la última:

INSERT INTO categorias (nombre, descripcion) VALUES
    ('Jardinería', 'Herramientas de jardín'),
    ('Mascotas', 'Productos para mascotas');
 
SELECT LAST_INSERT_ID();

Si los IDs asignados son 20 y 21, LAST_INSERT_ID() devuelve 20. Puedes calcular los demás porque AUTO_INCREMENT asigna valores consecutivos: el segundo será 21, el tercero 22, etc.

INSERT IGNORE con múltiples filas

INSERT IGNORE es especialmente útil con inserciones múltiples. Sin IGNORE, un duplicado en cualquier fila cancela toda la operación. Con IGNORE, las filas duplicadas se saltan y las demás se insertan:

INSERT IGNORE INTO etiquetas_producto (producto_id, etiqueta) VALUES
    (1, 'premium'),
    (1, 'destacado'),
    (2, 'más vendido'),
    (2, 'destacado');
Query OK, 2 rows affected, 2 warnings (0.01 sec)
Records: 4  Duplicates: 2  Warnings: 2

De las 4 filas, 2 son duplicadas (el iPhone 15 Pro ya tiene la etiqueta 'premium' y el Samsung ya tiene 'más vendido'). MySQL inserta las 2 nuevas ('destacado' para ambos) y omite las duplicadas sin devolver un error.

Límites

MySQL tiene un límite en el tamaño máximo de un paquete de datos, controlado por la variable max_allowed_packet. El valor por defecto suele ser 64MB en versiones recientes. Si intentas insertar tantas filas que la sentencia supera este límite, MySQL devuelve un error.

Para inserciones masivas (decenas de miles de filas), es mejor dividir la operación en lotes de 1000-5000 filas cada uno. Puedes consultar el límite actual con:

SHOW VARIABLES LIKE 'max_allowed_packet';

Practica con INSERT múltiples filas

Usa el editor para insertar varias filas de una vez:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos INSERT INTO ... SELECT, que permite insertar datos tomándolos directamente del resultado de una consulta.

Escrito por Eduardo Lázaro