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

To Top