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
Подготавливаемые запросы
Использование множества выражений в подготавливаемом запросе не поддерживается.
См. также