multi_query
Aprenda a usar mysqli_multi_query() em PHP para executar várias instruções SQL em uma única chamada, com exemplos práticos e boas práticas.
Neste artigo, vamos nos concentrar na função mysqli_multi_query() em PHP, que executa uma ou mais instruções SQL em uma única chamada. Abordaremos sua sintaxe, parâmetros e valor de retorno, percorreremos um exemplo executável e explicaremos como ler com segurança vários conjuntos de resultados.
O que é mysqli_multi_query()?
mysqli_multi_query() é uma função embutida do PHP que envia uma ou mais instruções SQL, separadas por ponto e vírgula, ao servidor MySQL em uma única requisição. Ela faz parte da extensão MySQLi, a interface aprimorada do PHP para comunicação com o MySQL.
É útil quando você precisa executar um lote de instruções de uma só vez — por exemplo, populando várias tabelas na inicialização, ou executando um procedimento armazenado que retorna vários conjuntos de resultados. Como cada instrução ainda é executada de forma independente no servidor, mysqli_multi_query() não é um substituto para uma transação quando você precisa de comportamento tudo-ou-nada (veja Quando não usar).
Sintaxe
A função funciona nos estilos procedural e orientado a objetos:
// Procedural style
mysqli_multi_query(mysqli $mysqli, string $query): bool
// Object-oriented style
$mysqli->multi_query(string $query): boolParâmetros
| Parâmetro | Descrição |
|---|---|
$mysqli | Uma conexão válida retornada por mysqli_connect(). |
$query | Uma string com uma ou mais instruções SQL separadas por ponto e vírgula (;). |
Valor de retorno
Retorna false se a primeira instrução falhar, caso contrário retorna true. Um valor de retorno true indica apenas que a primeira consulta foi aceita — você deve iterar sobre os resultados para detectar erros nas instruções seguintes.
Como usar mysqli_multi_query()
Chame a função em uma conexão MySQLi válida com uma string de instruções separadas por ponto e vírgula, em seguida percorra os conjuntos de resultados. Veja um exemplo completo:
<?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);
?>Veja o que cada parte faz:
mysqli_connect()abre uma conexão com o banco de dados MySQL; abortamos cedo se ela falhar.- Construímos uma única string com duas instruções separadas por ponto e vírgula.
mysqli_multi_query()envia ambas as instruções ao servidor em uma única chamada.- O loop
do...whilelê cada conjunto de resultados em sequência.mysqli_store_result()armazena em buffer o resultado atual,mysqli_fetch_row()lê suas linhas emysqli_next_result()avança para o próximo. mysqli_close()libera a conexão.
Tratando múltiplos conjuntos de resultados
Esta é a parte que os desenvolvedores mais frequentemente erram. Após um mysqli_multi_query() bem-sucedido, você deve consumir todos os conjuntos de resultados — inclusive os vazios produzidos por INSERT ou UPDATE — antes de executar outra consulta na mesma conexão. Ignorar esta etapa gera o erro "Commands out of sync".
O padrão seguro é:
<?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() retorna false quando não há mais resultados, encerrando o loop. Verificar mysqli_more_results() primeiro evita que um aviso seja emitido após a última instrução.
Quando não usar
mysqli_multi_query() é poderoso, mas fácil de usar incorretamente:
- Nunca passe entrada do usuário diretamente na string de consulta. Concatenar dados não confiáveis aqui é um vetor clássico de injeção SQL, e esta função não pode usar parâmetros vinculados. Para qualquer coisa que envolva entrada do usuário, execute cada instrução separadamente com prepared statements — veja
mysqli_prepare(). - Não é atômica. Se a segunda instrução falhar, a primeira já terá sido confirmada. Quando várias instruções precisam ter sucesso ou falhar juntas, envolva as consultas individuais em uma transação com
mysqli_begin_transaction(),mysqli_commit()emysqli_rollback(). - Sempre verifique o valor de retorno e itere os resultados para detectar erros nas instruções após a primeira.
Conclusão
A função mysqli_multi_query() permite executar várias instruções SQL em uma única chamada, o que é conveniente para operações em lote. A chave para usá-la corretamente é consumir todos os conjuntos de resultados com mysqli_next_result() para evitar erros de "Commands out of sync", e recorrer a prepared statements e transações sempre que entrada do usuário ou atomicidade estiverem envolvidas.