Comme pour presque toutes les questions "Comment puis-je utiliser SQL à partir de PHP ?" - Vous vraiment doit utiliser des déclarations préparées. Ce n'est pas si difficile :
$ids = array(2, 4, 6, 8);
// prepare an SQL statement with a single parameter placeholder
$sql = "UPDATE MyTable SET LastUpdated = GETDATE() WHERE id = ?";
$stmt = $mysqli->prepare($sql);
// bind a different value to the placeholder with each execution
for ($i = 0; $i < count($ids); $i++)
{
$stmt->bind_param("i", $ids[$i]);
$stmt->execute();
echo "Updated record ID: $id\n";
}
// done
$stmt->close();
Alternativement, vous pouvez le faire comme ceci :
$ids = array(2, 4, 6, 8);
// prepare an SQL statement with multiple parameter placeholders
$params = implode(",", array_fill(0, count($ids), "?"));
$sql = "UPDATE MyTable SET LastUpdated = GETDATE() WHERE id IN ($params)";
$stmt = $mysqli->prepare($sql);
// dynamic call of mysqli_stmt::bind_param hard-coded eqivalent
$types = str_repeat("i", count($ids)); // "iiii"
$args = array_merge(array($types), $ids); // ["iiii", 2, 4, 6, 8]
call_user_func_array(array($stmt, 'bind_param'), ref($args)); // $stmt->bind_param("iiii", 2, 4, 6, 8)
// execute the query for all input values in one step
$stmt->execute();
// done
$stmt->close();
echo "Updated record IDs: " . implode("," $ids) ."\n";
// ----------------------------------------------------------------------------------
// helper function to turn an array of values into an array of value references
// necessary because mysqli_stmt::bind_param needs value refereces for no good reason
function ref($arr) {
$refs = array();
foreach ($arr as $key => $val) $refs[$key] = &$arr[$key];
return $refs;
}
Ajoutez plus d'espaces réservés de paramètres pour d'autres champs selon vos besoins.
Lequel choisir ?
-
La première variante fonctionne avec un nombre variable d'enregistrements de manière itérative, atteignant la base de données plusieurs fois. Ceci est particulièrement utile pour les opérations UPDATE et INSERT.
-
La deuxième variante fonctionne également avec un nombre variable d'enregistrements, mais elle n'atteint la base de données qu'une seule fois. C'est beaucoup plus efficace que l'approche itérative, évidemment vous ne pouvez faire la même chose que pour tous les enregistrements concernés. Ceci est particulièrement utile pour les opérations SELECT et DELETE, ou lorsque vous souhaitez METTRE À JOUR plusieurs enregistrements avec les mêmes données.
Pourquoi préparer des relevés ?
- Les instructions préparées sont beaucoup plus sûres car elles rendent les attaques par injection SQL impossibles. C'est la principale raison d'utiliser des instructions préparées, même s'il est plus difficile de les écrire. Une bonne habitude à prendre est la suivante :utilisez toujours des instructions préparées, même si vous pensez que ce n'est "pas vraiment nécessaire". La négligence viendra vous mordre (ou vos clients).
- Réutiliser plusieurs fois la même instruction préparée avec différentes valeurs de paramètres est plus efficace que d'envoyer plusieurs chaînes SQL complètes à la base de données, car la base de données n'a besoin de compiler l'instruction qu'une seule fois et peut également la réutiliser.
- Seules les valeurs des paramètres sont envoyées à la base de données sur
execute()
, donc moins de données doivent passer par le réseau en cas d'utilisation répétée.
Dans les boucles plus longues, la différence de temps d'exécution entre l'utilisation d'une instruction préparée et l'envoi de SQL brut deviendra perceptible.