multi_query
Guida alla funzione mysqli_multi_query() in PHP per eseguire più query in una sola chiamata, con sintassi, parametri ed esempi pratici.
In questo articolo ci concentreremo sulla funzione mysqli_multi_query() in PHP, che esegue una o più istruzioni SQL in una singola chiamata. Ne analizzeremo la sintassi, i parametri e il valore di ritorno, vedremo un esempio eseguibile e spiegheremo come leggere in modo sicuro più set di risultati.
Cos'è mysqli_multi_query()?
mysqli_multi_query() è una funzione built-in di PHP che invia una o più istruzioni SQL, separate da punto e virgola, al server MySQL in un unico scambio di rete. Fa parte dell'estensione MySQLi, l'interfaccia migliorata di PHP per comunicare con MySQL.
È utile quando si dispone di un gruppo di istruzioni da eseguire tutte insieme — per esempio, per popolare più tabelle all'avvio o per eseguire una stored procedure che restituisce più set di risultati. Poiché ogni istruzione viene comunque eseguita in modo indipendente sul server, mysqli_multi_query() non sostituisce una transazione quando si ha bisogno di un comportamento tutto-o-niente (vedi Quando non usarla).
Sintassi
La funzione funziona sia nello stile procedurale che in quello orientato agli oggetti:
// Procedural style
mysqli_multi_query(mysqli $mysqli, string $query): bool
// Object-oriented style
$mysqli->multi_query(string $query): boolParametri
| Parametro | Descrizione |
|---|---|
$mysqli | Una connessione valida restituita da mysqli_connect(). |
$query | Una stringa con una o più istruzioni SQL separate da un punto e virgola (;). |
Valore di ritorno
Restituisce false se la prima istruzione fallisce, altrimenti true. Un valore di ritorno true significa solo che la prima query è stata accettata — è necessario iterare sui risultati per rilevare errori nelle istruzioni successive.
Come usare mysqli_multi_query()
Chiama la funzione su una connessione MySQLi valida con una stringa di istruzioni separate da punto e virgola, poi scorri i set di risultati. Ecco un esempio 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);
?>Ecco cosa fa ciascuna parte:
mysqli_connect()apre una connessione al database MySQL; se fallisce, si interrompe immediatamente.- Costruiamo una singola stringa contenente due istruzioni separate da punto e virgola.
mysqli_multi_query()invia entrambe le istruzioni al server in una sola chiamata.- Il ciclo
do...whilelegge ogni set di risultati a turno.mysqli_store_result()memorizza nel buffer il risultato corrente,mysqli_fetch_row()legge le sue righe emysqli_next_result()avanza al successivo. mysqli_close()rilascia la connessione.
Gestione di più set di risultati
Questa è la parte che gli sviluppatori sbagliano più spesso. Dopo un mysqli_multi_query() andato a buon fine, si deve consumare ogni set di risultati — anche quelli vuoti prodotti da INSERT o UPDATE — prima di poter eseguire un'altra query sulla stessa connessione. Saltare questo passaggio provoca un errore "Commands out of sync".
Il pattern sicuro è:
<?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() restituisce false quando non ci sono altri risultati, uscendo così dal ciclo. Verificare prima mysqli_more_results() evita l'emissione di un avviso dopo l'ultima istruzione.
Quando non usarla
mysqli_multi_query() è potente ma facile da usare male:
- Non passare mai direttamente input dell'utente nella stringa della query. Concatenare dati non attendibili qui rappresenta un classico vettore di SQL injection, e questa funzione non supporta parametri vincolati. Per qualsiasi cosa che coinvolga input dell'utente, eseguire ciascuna istruzione separatamente con istruzioni preparate — vedi
mysqli_prepare(). - Non è atomica. Se la seconda istruzione fallisce, la prima è già stata eseguita. Quando più istruzioni devono avere successo o fallire insieme, racchiudi le singole query in una transazione con
mysqli_begin_transaction(),mysqli_commit()emysqli_rollback(). - Controlla sempre il valore di ritorno e itera i risultati per intercettare errori nelle istruzioni successive alla prima.
Conclusione
La funzione mysqli_multi_query() consente di eseguire più istruzioni SQL in una singola chiamata, il che è comodo per le operazioni batch. La chiave per usarla correttamente è consumare ogni set di risultati con mysqli_next_result() per evitare errori "Commands out of sync", e ricorrere alle istruzioni preparate e alle transazioni ogni volta che sono coinvolti input dell'utente o è richiesta l'atomicità.