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