Inserire più record in un database MySQL con PHP
Inserire più record nel database in una sola volta aumenta notevolmente l'efficienza dell'applicazione, specialmente con grandi quantità di dati.
Inserire i record uno alla volta significa un round trip al server del database per ogni riga — lento e inefficiente quando si hanno centinaia o migliaia di righe da caricare. Raggrupparle in un'unica istruzione INSERT consente a MySQL di analizzare, pianificare e applicare l'intero batch in una sola operazione, risultando notevolmente più veloce.
Questo capitolo illustra tre modi per inserire più righe con l'estensione mysqli di PHP:
- Un'unica istruzione
INSERT ... VALUES (...), (...)— il metodo più semplice e veloce per l'inserimento in blocco. - Uno statement preparato iterato sui dati — sicuro contro le SQL injection, ideale quando i valori provengono dagli utenti.
mysqli_multi_query()— esecuzione di più istruzioni distinte concatenate in una sola stringa.
Se non hai ancora stabilito una connessione al database, inizia con Connessione a MySQL con PHP. Per l'inserimento di una singola riga, consulta Inserire dati in MySQL.
Stabilire una connessione
Ogni esempio di seguito presuppone una connessione mysqli aperta in $conn. La creiamo con mysqli_connect() e usciamo subito in caso di errore:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "database_name";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>Metodo 1: un INSERT con più set di valori
Il modo più veloce per aggiungere molte righe è un'unica istruzione INSERT INTO che elenca più set di valori separati da virgola. MySQL li inserisce tutti in un'unica operazione:
<?php
$sql = "INSERT INTO users (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]'),
('Mary', 'Moe', '[email protected]'),
('Julie', 'Dooley', '[email protected]')";
if (mysqli_query($conn, $sql)) {
// mysqli_affected_rows() reports how many rows were inserted
$count = mysqli_affected_rows($conn);
echo "$count records inserted successfully.";
} else {
echo "Error inserting records: " . mysqli_error($conn);
}
?>mysqli_query() accetta due argomenti — la connessione e la stringa SQL — e restituisce true in caso di successo o false in caso di errore. Dopo un inserimento riuscito, mysqli_affected_rows() indica quante righe sono state effettivamente scritte (in questo caso, 3).
Usa questo metodo quando i dati sono affidabili (codificati direttamente o già sanificati). Poiché i valori vengono concatenati direttamente nella stringa SQL, non è sicuro per l'input grezzo degli utenti — è esattamente ciò che risolve il Metodo 2.
Metodo 2: statement preparato in un ciclo
Quando i valori provengono da un modulo, da un'API o da qualsiasi fonte non affidabile, costruisci la query con uno statement preparato in modo che i dati vengano inviati separatamente dall'SQL. Questo blocca le SQL injection e consente di riutilizzare lo stesso statement compilato per ogni riga:
<?php
$users = [
['John', 'Doe', '[email protected]'],
['Mary', 'Moe', '[email protected]'],
['Julie', 'Dooley', '[email protected]'],
];
// Prepare once with placeholders
$stmt = mysqli_prepare($conn, "INSERT INTO users (firstname, lastname, email) VALUES (?, ?, ?)");
// Bind PHP variables to the placeholders ("sss" = three strings)
mysqli_stmt_bind_param($stmt, "sss", $firstname, $lastname, $email);
foreach ($users as [$firstname, $lastname, $email]) {
mysqli_stmt_execute($stmt); // runs with the current variable values
}
echo count($users) . " records inserted safely.";
mysqli_stmt_close($stmt);
?>La stringa di tipo "sss" indica a MySQL che i tre parametri associati sono stringhe. Usa i per gli interi, d per i double/float e b per i blob. Per una guida completa, consulta PHP MySQL Prepared Statements.
Per la massima velocità con migliaia di righe, racchiudi il ciclo in una transazione in modo che MySQL esegua il commit una sola volta anziché dopo ogni esecuzione:
<?php
mysqli_begin_transaction($conn);
foreach ($users as [$firstname, $lastname, $email]) {
mysqli_stmt_execute($stmt);
}
mysqli_commit($conn);
?>Metodo 3: mysqli_multi_query()
I metodi precedenti inseriscono in una tabella con un'unica istruzione. Quando devi eseguire più istruzioni diverse contemporaneamente — ad esempio inserendo in due tabelle — usa mysqli_multi_query(), che esegue più istruzioni SQL separate da punto e virgola da un'unica stringa:
<?php
$sql = "INSERT INTO users (firstname, lastname) VALUES ('John', 'Doe');";
$sql .= "INSERT INTO users (firstname, lastname) VALUES ('Mary', 'Moe');";
$sql .= "INSERT INTO logs (action) VALUES ('bulk import')";
if (mysqli_multi_query($conn, $sql)) {
echo "Multiple statements executed successfully.";
} else {
echo "Error: " . mysqli_error($conn);
}
?>Attenzione:
mysqli_multi_query()accetta istruzioni arbitrariamente concatenate, quindi è rischioso con qualsiasi input fornito dagli utenti — non costruire mai la sua stringa con dati non affidabili. Per semplici inserimenti in blocco, preferisci il Metodo 1 o il Metodo 2.
Ottenere gli ID inseriti
Dopo l'inserimento, mysqli_insert_id() restituisce l'id AUTO_INCREMENT generato dall'ultima riga inserita. Con un inserimento multi-riga restituisce l'id della prima riga del batch; le righe successive seguono sequenzialmente. Consulta Ottenere l'ID dell'ultimo record inserito per i dettagli.
Chiudere la connessione
mysqli chiude la connessione automaticamente al termine dello script, ma è buona pratica rilasciarla esplicitamente quando si è finito:
<?php
mysqli_close($conn);
?>Quale metodo dovrei usare?
| Situazione | Scelta migliore |
|---|---|
| Dati affidabili e fissi; massima velocità | Metodo 1 — un INSERT con più valori |
| Valori provenienti dagli utenti / input esterno | Metodo 2 — ciclo con statement preparato |
| Più istruzioni diverse contemporaneamente | Metodo 3 — mysqli_multi_query() |
Conclusione
Raggruppare gli inserimenti trasforma molti round trip lenti in un'unica operazione veloce. Opta per un singolo INSERT multi-valore quando i dati sono affidabili, per un ciclo con statement preparato (racchiuso in una transazione per batch di grandi dimensioni) quando provengono dagli utenti, e per mysqli_multi_query() solo quando hai effettivamente bisogno di eseguire istruzioni distinte insieme. Qualunque sia il metodo, valida l'input e controlla mysqli_error() affinché i fallimenti non passino mai inosservati.