## Sentencias Múltiples

MySQL permite opcionalmente tener múltiples sentencias en una cadena de sentencias. El envío de múltiples sentencias de una sola vez reduce los viajes de ida y vuelta desde el cliente al servidor, pero requiere un manejo especial.

Las sentencias múltiples o multiconsultas deben ser ejecutadas con mysqli_multi_query(). Las sentencias individuales de la cadena de sentencias están serparadas por un punto y coma. Entonces, todos los conjuntos de resultados devueltos por las sentencias ejecutadas deben ser obtenidos.

El servidor MySQL permite tener sentencias que devuelven conjuntos de resultados y sentencias que no devuelve conjuntos de resultados en una sentencia múltiple.

Ejemplo #1 Sentencias múltiples

`<?php
$mysqli = new mysqli("ejemplo.com", "usuario", "contraseña", "basedatos");
if ($mysqli->connect_errno) {
echo "Falló la conexión a MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
if (!$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
echo "Falló la creación de la tabla: (" . $mysqli->errno . ") " . $mysqli->error;
}
$sql = "SELECT COUNT(*) AS _num FROM test; ";
$sql.= "INSERT INTO test(id) VALUES (1); ";
$sql.= "SELECT COUNT(*) AS _num FROM test; ";
if (!$mysqli->multi_query($sql)) {
echo "Falló la multiconsulta: (" . $mysqli->errno . ") " . $mysqli->error;
}
do {
if ($resultado = $mysqli->store_result()) {
var_dump($resultado->fetch_all(MYSQLI_ASSOC));
$resultado->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
?>`

El resultado del ejemplo sería:

    array(1) {
      [0]=>
      array(1) {
        ["_num"]=>
        string(1) "0"
      }
    }
    array(1) {
      [0]=>
      array(1) {
        ["_num"]=>
        string(1) "1"
      }
    }

Consideraciones de seguridad

Las funciones de la API mysqli_query() y mysqli_real_query() no establecen una bandera de conexión necesaria para activar las multiconsultas en el servidor. Se usa una llamada extra a la API para las sentencias múltiples para reducir la verosimilitud de los ataques de inyecciones SQL accidentales. Un atacante puede intentar añadir sentencias como `; DROP DATABASE mysql` o `; SELECT SLEEP(999)`. Si el atacante tiene éxito al añadir SQL a la cadena de sentencias pero no se usa `mysqli_multi_query`, el servidor no ejecutará la segunda sentencia SQL inyectada y maliciosa.

Ejemplo #2 Inyección SQL

`<?php
$mysqli = new mysqli("ejemplo.com", "usuario", "contraseña", "basedatos");
$resultado = $mysqli->query("SELECT 1; DROP TABLE mysql.user");
if (!$resultado) {
echo "Error al ejecutar la consulta: (" . $mysqli->errno . ") " . $mysqli->error;
}
?>`

El resultado del ejemplo sería:

    Error al ejecutar la consulta: (1064) You have an error in your SQL syntax;
    check the manual that corresponds to your MySQL server version for the right syntax
    to use near 'DROP TABLE mysql.user' at line 1

Sentencias preparadas

El uso de sentencias múltiples con sentencias preparadas no está soportado.

See also

- mysqli::query()
- mysqli::multi_query()
- mysqli_result::next-result()
- mysqli_result::more-results()