Множественные запросы


MySQL поддерживает наличие нескольких SQL предложений в тексте одного запроса. Пересылка на сервер нескольких выражений в одном запроса уменьшает количество клиент-серверных взаимодействий, но требует специальной обработки.

Множественные запросы, или мультизапросы, должны запускаться функцией mysqli_multi_query(). Отдельные SQL предложения в мультизапросе отделяются точкой с запятой. После выполнения мультизапроса все результирующие наборы, которые он вернул, необходимо извлечь.

MySQL сервер поддерживает наличие в одном мультизапросе подзапросов, как возвращающих результирующий набор, так и не возвращающих.

Пример #1 Множественные запросы

<?php
$mysqli 
= new mysqli("example.com""user""password""database");
if (
$mysqli->connect_errno) {
    echo 
"Не удалось подключиться к MySQL: (" $mysqli->connect_errno ") " $mysqli->connect_error;
}

if (!
$mysqli->query("DROP TABLE IF EXISTS test") || !$mysqli->query("CREATE TABLE test(id INT)")) {
    echo 
"Не удалось создать таблицу: (" $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 
"Не удалось выполнить мультизапрос: (" $mysqli->errno ") " $mysqli->error;
}

do {
    if (
$res $mysqli->store_result()) {
        
var_dump($res->fetch_all(MYSQLI_ASSOC));
        
$res->free();
    }
} while (
$mysqli->more_results() && $mysqli->next_result());
?>

Результат выполнения данного примера:

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

Рассмотрение аспектов безопасности

Фунции API mysqli_query() и mysqli_real_query() во время работы не устанавливают на сервере специальный флаг, необходимый для выполнения мультизапросов. Отдельная API фунция для мультизапросов позволяет снизить вероятность случайных SQL инъекций. Злоумышленник может попытаться добавить в конец запроса выражения, вроде ; DROP DATABASE mysql или ; SELECT SLEEP(999). Если ему это удастся, но не будет использоваться фунция mysqli_multi_query, сервер не выполнит второе внедренное и опасное SQL выражение.

Пример #2 SQL инъекция

<?php
$mysqli 
= new mysqli("example.com""user""password""database");
$res    $mysqli->query("SELECT 1; DROP TABLE mysql.user");
if (!
$res) {
    echo 
"Ошибка при выполнении запроса: (" $mysqli->errno ") " $mysqli->error;
}
?>

Результат выполнения данного примера:

 Ошибка при выполнении запроса: (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 

Подготавливаемые запросы

Использование множества выражений в подготавливаемом запросе не поддерживается.

См. также