Допустим, у меня есть подготовленный запрос:
$update_rq = $DB->prepare("UPDATE `table`
SET
`A` = :a,
`B` = :b,
`C` = :c
WHERE `id` = :id
LIMIT 1
");
Если я выполню этот запрос со следующим кодом:
$update_rq->execute(['id' => $id,'a' => 1,'b' => 2]);
Я думаю, что этот запрос будет устанавливать C
колонка с NULL
значение (если этот столбец может иметь значение NULL или он выдаст ошибку, если не может).
Могу ли я изменить prepare
или же execute
заявления, чтобы изменить это поведение, чтобы сохранить C
столбец без изменений (SET C = C
) если соответствующая переменная не установлена (равно NULL)?
Другой подход: Возможно, я мог бы получить строку до обновления, изменить необходимые столбцы, а затем обновить с новыми значениями?
То, что вы делаете, не сработает, вам нужно привязать столько же параметров, сколько у вас есть заполнители. PHP не будет неявно заменять null
, это просто потерпит неудачу. Вы можете сделать что-то простое, как:
$data = array('a' => 1, 'b' => 2, 'c' => null);
$data = array_filter($data);
$placeholders = array_map(function ($col) { return "`$col` = :$col"; }, array_keys($data));
$query = sprintf('UPDATE `table` SET %s WHERE id = :id', join(', ', $placeholders));
$stmt = $DB->prepare($query);
$stmt->execute($data + array('id' => $id));
Это выполняет оператор с точно таким же количеством заполнителей и значений, как есть; любой null
значения полностью игнорируются. Позаботьтесь о том, чтобы внести белые имена в столбцы; Это означает, что вы не должны принимать произвольные имена столбцов в качестве пользовательского ввода, так как "`$col` = :$col"
шаг открывает вас до внедрения SQL. По крайней мере, сделать что-то вроде:
$allowedCols = array('a', 'b', 'c');
if (array_diff_key($_POST, array_flip($allowedCols))) {
throw new UnexpectedValueException('Received invalid data');
}
Других решений пока нет …