Ответ 1
Как и почти все вопросы "Как делать SQL изнутри PHP" - вы действительно должны использовать подготовленные инструкции. Это не так сложно:
$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();
В качестве альтернативы вы можете сделать это следующим образом:
$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;
}
Добавьте дополнительные заполнители параметров для других полей, которые вам нужны.
Какой из них выбрать?
-
Первый вариант работает с переменным числом записей итеративно, несколько раз ударяя базу данных. Это наиболее полезно для операций UPDATE и INSERT.
-
Второй вариант также работает с переменным количеством записей, но он попадает в базу данных только один раз. Это намного эффективнее, чем итеративный подход, очевидно, что вы можете сделать одно и то же для всех затронутых записей. Это наиболее полезно для операций SELECT и DELETE, или если вы хотите ОБНОВИТЬ несколько записей с теми же данными.
Зачем готовые заявления?
- Подготовленные утверждения намного безопаснее, потому что они делают атаки SQL-инъекций невозможными. Это основная причина для использования подготовленных операторов, даже если их больше писать. Разумная привычка вступать в это: всегда используйте подготовленные заявления, даже если вы считаете, что это "не обязательно". Пренебрежение придет и укусит вас (или ваших клиентов).
- Повторное использование одного и того же подготовленного оператора несколько раз с разными значениями параметров более эффективно, чем отправка нескольких полных строк SQL в базу данных, потому что базе данных нужно только один раз скомпилировать инструкцию и также повторно использовать ее.
- В базу данных на
execute()
отправляются только значения параметров, поэтому при повторном использовании требуется меньшее количество данных.
В более длинных циклах разница времени выполнения между использованием подготовленного оператора и отправкой обычного SQL станет заметной.