next_result
Saiba como usar a função mysqli_next_result() do PHP para preparar o próximo conjunto de resultados de mysqli_multi_query().
Quando você envia várias instruções SQL ao MySQL em uma única chamada com mysqli_multi_query(), o servidor retorna os resultados um conjunto de cada vez. mysqli_next_result() é a função que avança do conjunto de resultados atual para o próximo, permitindo percorrer todos eles em um loop. Este artigo explica o que a função retorna, os parâmetros que aceita, os erros mais comuns e como utilizá-la nos estilos procedural e orientado a objetos do MySQLi.
O que mysqli_next_result() faz
mysqli_next_result() prepara o próximo conjunto de resultados de uma chamada anterior a mysqli_multi_query() e o disponibiliza para funções de recuperação como mysqli_store_result() ou mysqli_fetch_assoc(). Internamente, o MySQL armazena em buffer todos os conjuntos de resultados de uma multi-query; essa função avança o ponteiro interno em uma posição.
Importante: uma única chamada a mysqli_next_result() avança apenas um passo. Para processar todas as instruções, chame-a dentro de um loop até não restar mais resultados.
Sintaxe
// Procedural style
mysqli_next_result(mysqli $mysql): bool
// Object-oriented style
$mysqli->next_result(): boolParâmetros
$mysql(somente procedural) — o objeto de conexão retornado pormysqli_connect(). No estilo OOP, é o objeto sobre o qual o método é chamado.
Valor de retorno
Retorna um boolean:
true— o próximo conjunto de resultados foi preparado com sucesso (ou não havia mais resultados e nenhum erro ocorreu).false— houve um erro na próxima instrução, ou a query anterior não tinha resultados em buffer para avançar.
Para distinguir "não há mais resultados" de "a próxima instrução falhou", use em conjunto com mysqli_more_results(): se mysqli_more_results() for true mas mysqli_next_result() retornar false, a próxima instrução gerou um erro.
Como usar mysqli_next_result() (estilo procedural)
Execute o lote com mysqli_multi_query(), processe o primeiro conjunto de resultados e, em seguida, faça um loop enquanto houver mais resultados, avançando com mysqli_next_result() a cada iteração:
<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");
if (!$mysqli) {
die("Connection failed: " . mysqli_connect_error());
}
$query = "SELECT name FROM users LIMIT 1;";
$query .= "SELECT title FROM posts LIMIT 1;";
if (mysqli_multi_query($mysqli, $query)) {
do {
// mysqli_store_result() returns false for statements that
// produce no rows (INSERT, UPDATE, DELETE), so guard with if.
if ($result = mysqli_store_result($mysqli)) {
while ($row = mysqli_fetch_assoc($result)) {
print_r($row);
}
mysqli_free_result($result);
}
// Stop when there are no more results; otherwise advance.
} while (mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
} else {
echo "Multi-query failed: " . mysqli_error($mysqli);
}
mysqli_close($mysqli);
?>A condição do do...while é a ideia central: mysqli_more_results() verifica se existe outro conjunto, e mysqli_next_result() avança para ele. Como && usa avaliação em curto-circuito, mysqli_next_result() só é chamada quando realmente existe outro resultado, evitando o aviso que ocorreria ao chamá-la após o último conjunto.
Estilo orientado a objetos
A mesma lógica com a API OOP fica um pouco mais limpa:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->connect_errno) {
die("Connection failed: " . $mysqli->connect_error);
}
$sql = "SELECT name FROM users LIMIT 1;";
$sql .= "SELECT title FROM posts LIMIT 1;";
if ($mysqli->multi_query($sql)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
print_r($row);
}
$result->free();
}
} while ($mysqli->more_results() && $mysqli->next_result());
}
$mysqli->close();
?>Erros comuns
- Sempre esvazie a fila. Se você executar outra query enquanto conjuntos de resultados de um
mysqli_multi_query()anterior ainda estiverem pendentes, o MySQLi lançará "Commands out of sync". Faça um loop commysqli_next_result()até quemysqli_more_results()sejafalseantes de emitir uma nova query. - Esquecer
mysqli_store_result()para instruções não-SELECT. Instruções comoINSERTnão produzem conjunto de resultados, entãomysqli_store_result()retornafalse— isso é esperado, não é um erro. A proteção comif ($result = ...)trata esse caso. - Multi-query é um risco de injeção SQL. Passe apenas SQL confiável e controlado pelo servidor para
mysqli_multi_query(). Nunca concatene entrada do usuário em uma string de múltiplas instruções; use prepared statements para dados do usuário.
Conclusão
mysqli_next_result() é a função que permite percorrer todos os conjuntos de resultados retornados por uma única chamada a mysqli_multi_query(). Usada em conjunto com mysqli_more_results() dentro de um loop do...while, permite processar a saída de cada instrução com segurança e mantém a conexão sincronizada. Para mais informações sobre o fluxo de trabalho relacionado, consulte mysqli_multi_query() e mysqli_fetch_assoc().