2012-02-22 4 views
3

Как обновить сразу несколько строк?Обновление нескольких строк одним запросом

Как: UPDATE table SET a = ? WHERE b = ? AND c = 1

но для многих строк. В ? параметры являются массивами ...

Я прочитал this answer но он использует СЛУЧАЙ, и я не думаю, что я могу сделать это ...


Сейчас у меня есть что-то вроде этого:

foreach($values as $key => $value) 
    $res = $pdo->prepare('UPDATE table SET a = ? WHERE b = ? AND c = 1'); 
    $res->execute(array($value, $key)); 
} 
+0

вы имеете в виду они представляют собой пары? –

+0

Почему вы не можете использовать CASE? – DarkAjax

+0

, потому что запрос будет огромным ... – Alex

ответ

6

Чтобы сделать это за один проход запроса, вам необходимо использовать CASE и assemble the parameters programmatically. SQL не поддерживает переменные подготовленные операторы, и только simple values может быть параметризован.

В качестве альтернативы, определите оператор, чтобы принимать данные только по одной строке за один раз и запускать запрос в цикле. Повторное выполнение - это то, как подготовленные заявления предназначены для использования в таких случаях.

try { 
    $query = $db->prepare('UPDATE table SET a = ? WHERE b = ? AND c = 1'); 
    foreach ($as as $i => $a) { 
     $query->execute(array($a, $bs[$i])); 
    } 
} catch (PDOException $e) { 
    ... 
} 
+0

вы можете создать оператор case и по-прежнему использовать подготовленные инструкции для SQL Injection или вам нужно будет избежать каждого входа «как старые дни» – JM4

+0

@ JM4: это зависит от того, что вам нужно параметризовать. Подготовленные утверждения аналогичны функциям, но могут быть параметризованы только значения (а не, например, имена столбцов). Пока это все, что вам нужно, готовое заявление будет работать нормально. Тем не менее, я рекомендую решение, аналогичное моему образцу кода, поскольку оно проще в целом. В отличие от функций, аргументы готовых операторов не могут быть повторно использованы, вообще говоря, поэтому вместо этого вам придется иметь отдельные параметры и повторять значения, которые подвержены ошибкам. – outis

4

Используйте метод CASE, как описано в предоставленной вами ссылке, но динамически создавайте запрос со значениями, которые вы хотите.

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

+0

Единственным недостатком этого (и это сама рекомендация) является то, что вы не можете избежать введенных данных с помощью подготовленных операторов, как в противном случае в операторах одной строки. – JM4

2

Другим способом было бы вставить свои ключевые пары значений (все сразу) во временную таблицу, то сделать что-то вроде этого:

UPDATE table t 
SET t.a = (SELECT p.a FROM tmp p WHERE p.b = t.b) 
WHERE t.b IN (SELECT p.b FROM tmp p) AND t.c = 1 
Смежные вопросы