Insertar múltiples registros en una base de datos MySQL con PHP
Aprende tres formas de insertar múltiples registros en MySQL con PHP: INSERT múltiple, sentencias preparadas y mysqli_multi_query().
Insertar registros de uno en uno implica un viaje de ida y vuelta al servidor de base de datos por cada fila — lento e ineficiente cuando tienes cientos o miles de filas que cargar. Agruparlos en una única sentencia INSERT permite que MySQL analice, planifique y confirme el lote completo de una sola vez, lo que resulta considerablemente más rápido.
Este capítulo muestra tres formas de insertar múltiples filas con la extensión mysqli de PHP:
- Una única sentencia
INSERT ... VALUES (...), (...)— la inserción masiva más simple y rápida. - Una sentencia preparada iterada sobre tus datos — segura contra inyección SQL, ideal cuando los valores provienen de usuarios.
mysqli_multi_query()— ejecutar varias sentencias distintas agrupadas en una sola cadena.
Si aún no te has conectado a una base de datos, empieza por Conectar a MySQL con PHP. Para insertar una sola fila, consulta Insertar datos en MySQL.
Establecer una conexión
Todos los ejemplos a continuación asumen una conexión mysqli abierta en $conn. La creamos con mysqli_connect() y detenemos la ejecución de inmediato si falla:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "database_name";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>Método 1: Un INSERT con múltiples conjuntos de valores
La forma más rápida de añadir muchas filas es una única sentencia INSERT INTO que enumera varios conjuntos de valores separados por comas. MySQL los inserta todos en una sola operación:
<?php
$sql = "INSERT INTO users (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]'),
('Mary', 'Moe', '[email protected]'),
('Julie', 'Dooley', '[email protected]')";
if (mysqli_query($conn, $sql)) {
// mysqli_affected_rows() reports how many rows were inserted
$count = mysqli_affected_rows($conn);
echo "$count records inserted successfully.";
} else {
echo "Error inserting records: " . mysqli_error($conn);
}
?>mysqli_query() recibe dos argumentos — la conexión y la cadena SQL — y devuelve true en caso de éxito o false en caso de fallo. Tras una inserción exitosa, mysqli_affected_rows() indica cuántas filas se escribieron realmente (en este caso, 3).
Usa este método cuando los datos son de confianza (codificados de forma fija o ya saneados). Dado que los valores se concatenan directamente en la cadena SQL, no es seguro para entradas brutas de usuarios — eso es lo que soluciona el Método 2.
Método 2: Sentencia preparada en un bucle
Cuando los valores provienen de un formulario, una API o cualquier fuente no confiable, construye la consulta con una sentencia preparada para que los datos se envíen por separado del SQL. Esto bloquea la inyección SQL y permite reutilizar la misma sentencia compilada para cada fila:
<?php
$users = [
['John', 'Doe', '[email protected]'],
['Mary', 'Moe', '[email protected]'],
['Julie', 'Dooley', '[email protected]'],
];
// Prepare once with placeholders
$stmt = mysqli_prepare($conn, "INSERT INTO users (firstname, lastname, email) VALUES (?, ?, ?)");
// Bind PHP variables to the placeholders ("sss" = three strings)
mysqli_stmt_bind_param($stmt, "sss", $firstname, $lastname, $email);
foreach ($users as [$firstname, $lastname, $email]) {
mysqli_stmt_execute($stmt); // runs with the current variable values
}
echo count($users) . " records inserted safely.";
mysqli_stmt_close($stmt);
?>La cadena de tipo "sss" indica a MySQL que los tres parámetros enlazados son cadenas. Usa i para enteros, d para doubles/floats y b para blobs. Para un recorrido completo, consulta Sentencias preparadas en PHP MySQL.
Para máxima velocidad con miles de filas, envuelve el bucle en una transacción para que MySQL confirme una sola vez en lugar de hacerlo después de cada ejecución:
<?php
mysqli_begin_transaction($conn);
foreach ($users as [$firstname, $lastname, $email]) {
mysqli_stmt_execute($stmt);
}
mysqli_commit($conn);
?>Método 3: mysqli_multi_query()
Los métodos anteriores insertan en una tabla con una sentencia. Cuando necesitas ejecutar varias sentencias distintas a la vez — por ejemplo, insertar en dos tablas — usa mysqli_multi_query(), que ejecuta múltiples sentencias SQL separadas por punto y coma desde una única cadena:
<?php
$sql = "INSERT INTO users (firstname, lastname) VALUES ('John', 'Doe');";
$sql .= "INSERT INTO users (firstname, lastname) VALUES ('Mary', 'Moe');";
$sql .= "INSERT INTO logs (action) VALUES ('bulk import')";
if (mysqli_multi_query($conn, $sql)) {
echo "Multiple statements executed successfully.";
} else {
echo "Error: " . mysqli_error($conn);
}
?>Precaución:
mysqli_multi_query()acepta sentencias apiladas de forma arbitraria, por lo que es arriesgado con cualquier entrada suministrada por el usuario — nunca construyas su cadena a partir de datos no confiables. Para inserciones masivas simples, prefiere el Método 1 o el Método 2.
Obtener los IDs insertados
Tras insertar, mysqli_insert_id() devuelve el id AUTO_INCREMENT generado por la última fila insertada. Con una inserción de múltiples filas, devuelve el id de la primera fila del lote; las filas siguientes se suceden de forma secuencial. Consulta Obtener el ID del último registro insertado para más detalles.
Cerrar la conexión
mysqli cierra la conexión automáticamente cuando finaliza el script, pero es una buena práctica liberarla explícitamente una vez que hayas terminado:
<?php
mysqli_close($conn);
?>¿Qué método debo usar?
| Situación | Mejor opción |
|---|---|
| Datos de confianza y fijos; máxima velocidad | Método 1 — un INSERT con múltiples valores |
| Valores de usuarios / entrada externa | Método 2 — bucle con sentencia preparada |
| Varias sentencias distintas a la vez | Método 3 — mysqli_multi_query() |
Conclusión
Agrupar inserciones convierte muchos viajes lentos en una operación rápida. Recurre a un único INSERT de múltiples valores cuando los datos son de confianza, a una sentencia preparada en bucle (envuelta en una transacción para lotes grandes) cuando provienen de usuarios, y a mysqli_multi_query() solo cuando realmente necesites ejecutar sentencias distintas juntas. Sea cual sea el método, valida tu entrada y comprueba mysqli_error() para que los fallos nunca pasen desapercibidos.