mysql — PDO PHP: могу ли я подготовить запрос, который не изменит столбец, если соответствующая переменная не установлена?

Допустим, у меня есть подготовленный запрос:

$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)?

Другой подход: Возможно, я мог бы получить строку до обновления, изменить необходимые столбцы, а затем обновить с новыми значениями?

0

Решение

То, что вы делаете, не сработает, вам нужно привязать столько же параметров, сколько у вас есть заполнители. 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');
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]