multi_query
В этой статье мы рассмотрим функцию mysqli_multi_query() в PHP для выполнения нескольких SQL-запросов за один вызов.
В этой статье мы рассмотрим функцию mysqli_multi_query() в PHP, которая выполняет один или несколько SQL-операторов за один вызов. Мы разберём её синтаксис, параметры и возвращаемое значение, рассмотрим рабочий пример и объясним, как безопасно читать несколько наборов результатов.
Что такое mysqli_multi_query()?
mysqli_multi_query() — это встроенная функция PHP, которая отправляет один или несколько SQL-операторов, разделённых точками с запятой, на сервер MySQL за один запрос. Она является частью расширения MySQLi — улучшенного интерфейса PHP для работы с MySQL.
Функция удобна, когда нужно выполнить набор операторов сразу — например, заполнить несколько таблиц при инициализации или запустить хранимую процедуру, возвращающую несколько наборов результатов. Поскольку каждый оператор выполняется на сервере независимо, mysqli_multi_query() не заменяет транзакцию, если требуется поведение «всё или ничего» (см. Когда не следует использовать).
Синтаксис
Функция работает как в процедурном, так и в объектно-ориентированном стиле:
// Procedural style
mysqli_multi_query(mysqli $mysqli, string $query): bool
// Object-oriented style
$mysqli->multi_query(string $query): boolПараметры
| Параметр | Описание |
|---|---|
$mysqli | Действительное соединение, возвращённое mysqli_connect(). |
$query | Строка, содержащая один или несколько SQL-операторов, разделённых точкой с запятой (;). |
Возвращаемое значение
Функция возвращает false, если первый оператор завершился с ошибкой, и true в противном случае. Значение true означает лишь то, что первый запрос был принят — для обнаружения ошибок в последующих операторах необходимо перебрать все наборы результатов.
Как использовать mysqli_multi_query()
Вызовите функцию для действительного соединения MySQLi, передав строку операторов, разделённых точками с запятой, затем переберите наборы результатов в цикле. Ниже приведён полный пример:
<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");
if (!$mysqli) {
die("Connection failed: " . mysqli_connect_error());
}
$query = "INSERT INTO table1 VALUES ('value1', 'value2', 'value3');";
$query .= "UPDATE table2 SET column1 = 'newvalue' WHERE id = 1;";
if (mysqli_multi_query($mysqli, $query)) {
do {
if ($result = mysqli_store_result($mysqli)) {
while ($row = mysqli_fetch_row($result)) {
print_r($row);
}
mysqli_free_result($result);
}
} while (mysqli_next_result($mysqli));
} else {
echo "Error: " . mysqli_error($mysqli);
}
mysqli_close($mysqli);
?>Что делает каждая часть:
mysqli_connect()открывает соединение с базой данных MySQL; если это не удалось, выполнение прерывается.- Формируется одна строка, содержащая два оператора, разделённых точками с запятой.
mysqli_multi_query()отправляет оба оператора на сервер за один вызов.- Цикл
do...whileпоследовательно читает каждый набор результатов.mysqli_store_result()буферизует текущий результат,mysqli_fetch_row()читает его строки, аmysqli_next_result()переходит к следующему набору. mysqli_close()освобождает соединение.
Обработка нескольких наборов результатов
Это та часть, где разработчики чаще всего допускают ошибки. После успешного выполнения mysqli_multi_query() вы обязаны считать каждый набор результатов — даже пустые, создаваемые операторами INSERT или UPDATE — прежде чем выполнить новый запрос на том же соединении. Пропуск этого шага вызовет ошибку «Commands out of sync».
Безопасный шаблон выглядит так:
<?php
do {
// Buffer the current result set, if any.
if ($result = mysqli_store_result($mysqli)) {
while ($row = mysqli_fetch_row($result)) {
print_r($row);
}
mysqli_free_result($result);
}
// mysqli_more_results() avoids a spurious warning on the last loop.
} while (mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
?>mysqli_next_result() возвращает false, когда больше нет результатов, что завершает цикл. Предварительная проверка mysqli_more_results() предотвращает вывод предупреждения после последнего оператора.
Когда не следует использовать
mysqli_multi_query() — мощная функция, которую легко использовать неправильно:
- Никогда не передавайте пользовательский ввод напрямую в строку запроса. Конкатенация ненадёжных данных здесь — классический вектор SQL-инъекции, а эта функция не поддерживает связанные параметры. Для любых операций с пользовательским вводом запускайте каждый оператор отдельно с использованием подготовленных запросов — см.
mysqli_prepare(). - Функция не является атомарной. Если второй оператор завершится с ошибкой, первый уже будет зафиксирован. Когда несколько операторов должны быть выполнены целиком или не выполнены вовсе, оборачивайте отдельные запросы в транзакцию с помощью
mysqli_begin_transaction(),mysqli_commit()иmysqli_rollback(). - Всегда проверяйте возвращаемое значение и перебирайте результаты, чтобы перехватывать ошибки в операторах после первого.
Заключение
Функция mysqli_multi_query() позволяет выполнить несколько SQL-операторов за один вызов, что удобно для пакетных операций. Ключ к правильному использованию — считывать каждый набор результатов с помощью mysqli_next_result(), чтобы избежать ошибок «Commands out of sync», а при наличии пользовательского ввода или необходимости атомарности использовать подготовленные запросы и транзакции.