W3docs

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);
?>

Что делает каждая часть:

  1. mysqli_connect() открывает соединение с базой данных MySQL; если это не удалось, выполнение прерывается.
  2. Формируется одна строка, содержащая два оператора, разделённых точками с запятой.
  3. mysqli_multi_query() отправляет оба оператора на сервер за один вызов.
  4. Цикл do...while последовательно читает каждый набор результатов. mysqli_store_result() буферизует текущий результат, mysqli_fetch_row() читает его строки, а mysqli_next_result() переходит к следующему набору.
  5. 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», а при наличии пользовательского ввода или необходимости атомарности использовать подготовленные запросы и транзакции.

Практика

Практика
Какова основная цель функции 'multi_query' в PHP?
Какова основная цель функции 'multi_query' в PHP?
Was this page helpful?