multi_query
Aprende a usar mysqli_multi_query() en PHP para ejecutar múltiples consultas en una sola llamada, con ejemplos y buenas prácticas de seguridad.
En este artículo nos centraremos en la función mysqli_multi_query() de PHP, que ejecuta una o más sentencias SQL en una sola llamada. Veremos su sintaxis, parámetros y valor de retorno, recorreremos un ejemplo ejecutable y explicaremos cómo leer varios conjuntos de resultados de forma segura.
¿Qué es mysqli_multi_query()?
mysqli_multi_query() es una función integrada de PHP que envía una o más sentencias SQL, separadas por punto y coma, al servidor MySQL en un único viaje de ida y vuelta. Forma parte de la extensión MySQLi, la interfaz mejorada de PHP para comunicarse con MySQL.
Es útil cuando se tiene un lote de sentencias que ejecutar de una vez — por ejemplo, al inicializar varias tablas o al ejecutar un procedimiento almacenado que devuelve varios conjuntos de resultados. Como cada sentencia se ejecuta de forma independiente en el servidor, mysqli_multi_query() no sustituye a una transacción cuando se necesita un comportamiento todo-o-nada (véase Cuándo no usarla).
Sintaxis
La función funciona tanto en estilo procedimental como orientado a objetos:
// Procedural style
mysqli_multi_query(mysqli $mysqli, string $query): bool
// Object-oriented style
$mysqli->multi_query(string $query): boolParámetros
| Parámetro | Descripción |
|---|---|
$mysqli | Una conexión válida devuelta por mysqli_connect(). |
$query | Una cadena con una o más sentencias SQL separadas por punto y coma (;). |
Valor de retorno
Devuelve false si la primera sentencia falla, y true en caso contrario. Un valor de retorno true solo indica que la primera consulta fue aceptada — es necesario iterar sobre los resultados para detectar errores en sentencias posteriores.
Cómo usar mysqli_multi_query()
Llama a la función sobre una conexión MySQLi válida con una cadena de sentencias separadas por punto y coma y, a continuación, recorre los conjuntos de resultados. A continuación se muestra un ejemplo completo:
<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");
if (!$mysqli) {
die("Connection failed: " . mysqli_connect_error());
}
$query = "INSERT INTO table1 VALUES ('value1', 'value2', 'value3');";
$query .= "UPDATE table2 SET column1 = 'newvalue' WHERE id = 1;";
if (mysqli_multi_query($mysqli, $query)) {
do {
if ($result = mysqli_store_result($mysqli)) {
while ($row = mysqli_fetch_row($result)) {
print_r($row);
}
mysqli_free_result($result);
}
} while (mysqli_next_result($mysqli));
} else {
echo "Error: " . mysqli_error($mysqli);
}
mysqli_close($mysqli);
?>Esto es lo que hace cada parte:
mysqli_connect()abre una conexión a la base de datos MySQL; si falla, se abandona la ejecución de inmediato.- Se construye una única cadena que contiene dos sentencias separadas por punto y coma.
mysqli_multi_query()envía ambas sentencias al servidor en una sola llamada.- El bucle
do...whilelee cada conjunto de resultados a su vez.mysqli_store_result()almacena en búfer el resultado actual,mysqli_fetch_row()lee sus filas ymysqli_next_result()avanza al siguiente. mysqli_close()libera la conexión.
Gestión de múltiples conjuntos de resultados
Esta es la parte que los desarrolladores más frecuentemente gestionan mal. Tras un mysqli_multi_query() exitoso, es obligatorio consumir todos los conjuntos de resultados — incluso los vacíos producidos por sentencias INSERT o UPDATE — antes de poder ejecutar otra consulta en la misma conexión. Saltarse este paso genera un error "Commands out of sync".
El patrón seguro es:
<?php
do {
// Buffer the current result set, if any.
if ($result = mysqli_store_result($mysqli)) {
while ($row = mysqli_fetch_row($result)) {
print_r($row);
}
mysqli_free_result($result);
}
// mysqli_more_results() avoids a spurious warning on the last loop.
} while (mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
?>mysqli_next_result() devuelve false cuando no hay más resultados, lo que hace salir del bucle. Comprobar mysqli_more_results() primero evita que se emita una advertencia después de la última sentencia.
Cuándo no usarla
mysqli_multi_query() es potente pero fácil de usar incorrectamente:
- Nunca pases entrada del usuario directamente en la cadena de consulta. Concatenar datos no confiables aquí es un vector clásico de inyección SQL, y esta función no admite parámetros enlazados. Para cualquier cosa que implique entrada del usuario, ejecuta cada sentencia por separado con sentencias preparadas — véase
mysqli_prepare(). - No es atómica. Si la segunda sentencia falla, la primera ya ha sido confirmada. Cuando varias sentencias deben tener éxito o fallar juntas, envuelve las consultas individuales en una transacción con
mysqli_begin_transaction(),mysqli_commit()ymysqli_rollback(). - Comprueba siempre el valor de retorno e itera los resultados para detectar errores en sentencias posteriores a la primera.
Conclusión
La función mysqli_multi_query() permite ejecutar varias sentencias SQL en una sola llamada, lo cual resulta conveniente para operaciones por lotes. La clave para usarla correctamente es consumir todos los conjuntos de resultados con mysqli_next_result() para evitar los errores "Commands out of sync", y recurrir a las sentencias preparadas y las transacciones siempre que haya entrada del usuario o se requiera atomicidad.