MySQL поддерживает наличие нескольких SQL-запросов в тексте одного запроса, но требует особого обращения. Пересылка на сервер нескольких выражений в одном запроса уменьшает количество клиент-серверных взаимодействий, но требует специальной обработки.
Множественные запросы, или мультизапросы, должны запускаться функцией mysqli::multi_query(). Отдельные SQL-предложения в мультизапросе отделяются точкой с запятой. После выполнения мультизапроса все результирующие наборы, которые он вернул, необходимо извлечь.
MySQL-сервер поддерживает наличие в одном мультизапросе подзапросов, как возвращающих результирующий набор, так и не возвращающих.
Пример #1 Множественные запросы
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$sql = "SELECT COUNT(*) AS _num FROM test;
INSERT INTO test(id) VALUES (1);
SELECT COUNT(*) AS _num FROM test; ";
$mysqli->multi_query($sql);
do {
if ($result = $mysqli->store_result()) {
var_dump($result->fetch_all(MYSQLI_ASSOC));
$result->free();
}
} while ($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_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$result = $mysqli->query("SELECT 1; DROP TABLE mysql.user");
?>
Результат выполнения данного примера:
PHP Fatal error: Uncaught mysqli_sql_exception: 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
Подготавливаемые запросы
Использование множества выражений в подготавливаемом запросе не поддерживается.
Смотрите также