Всем доброго времени суток! Возникла задача обновления ~30 строк в одной таблице. Что лучше использовать: загнать апдейты в цикл или использовать конструкцию update case? как это отразится на работоспособности? Заранее спасибо за ответы
в зависимости от того, как часто надо обновлять столько строк. если нечасто, то можно реализовать в цикле. если же часто - можно сделать в виде триггера на вставку, и делать всё одним запросом в виде вставки, а уже триггер будет проверять - если такая строка имеется, то обновить значения, если же нет - создать. если обновляется поле булевого типа (вкл/выкл), то можно реализовать обновление всего одним запросом типа UPDATE table SET enabled=False WHERE id IN(0, 1, 2, 3...) вообще вариантов много, зависит от того, что КОНКРЕТНО нужно сделать
уж легче тогда REPLACE, но к сожалению данная команда поддерживается только MySQL. PostgreSQL не поддерживает, насчёт Майкрософтовской БД - не знаю, но тоже врядли поддерживается, т.к. эта конструкция не является стандартом (а жаль, очень хорошая штука). А вот триггеры поддерживаются уже почти везде (разве только в sqlite нету :-D ) Если нам надо обновить всего одно поле? То тут уже REPLACE/ON DUPICATE UPDATE не поможет. Например, у нас три поля, а обновляются только два - их-то мы и посылаем команде обновить. Replace при дублирующемся первичном ключе удаляет старую строку, и вставляет новую. В итогде значение первого поля будет NULL, т.к. это поле мы не посылаем, а старое значение будет утеряно. В случае с триггером можно обновить только необходимые поля, сохраняя значения неуказанных полей, и вообще, обработать почти любую ситуацию и среагировать так, как пожелает разработчик.
Используется MySQL, myisam. В таблице 3 поля, одно из них обновляется (число) в зависимости от других двух. Обновляться данные будут нечасто, сделала через цикл. Gromo, спасибо
чет не сталкивался с таким. В доке что-то подобное читал, но, на самом деле проблем не было никогда. Очень гибкий и удобный механизм. Только обновляемые, при совпадении ключа(ей) поля обновляются и ничего не теряется =) проверял. Хотя, это, наверное, из-за того, что ты делаешь инсерт, (и только при существовании ключей делаешь апдейт) и следовательно, значения всех полей у тебя есть Это если известно, что запись с ключом уже есть. Если сравнивать с insert on duplicate update - предварительно делать запрос на существование записи с ключом. Вариант с REPLACE будет медленнее
исходя из той документации, что я читал, предварительная запись удаляется. может быть сейчас это и не так, но стоит это иметь в виду. REPLACE и ON DUPLICATE UPDATE - это просто разные названия для одной и той же инструкции, так что по скорости разницы быть не должно.
Поздновато, но не могу пройти мимо, ради тех, кто придет после меня )) Не легче. Не стоит )) Вы не ту документацию читали - так, как говорите вы, не было никогда. INSERT ... ON DUPLICATE KEY UPDATE запись не удаляет, он обновляет ее при совпадении ключей, причем исключительно поля, указанные после слова UPDATE Посему претензии вроде актуальны только для REPLACE. Поэтому и по скорости отнюдь не то же самое, так как REPLACE при совпадении ключей делает DELETE, затем INSERT, а INSERT ... ON DUPLICATE KEY UPDATE ограничивается одним только UPDATE'ом. Так что это не совсем не просто ))
trashcan спасибо, просветили. я читал ту самую официальную документацию. просто был неправ в том, что replace и on duplicate update - это одна и та же конструкция. теперь осталось допилить эту (точнее, эти) конструкцию до стандарта (чтобы и postgresql поддерживалось) и будет вообще кошерно.
если вы читали документацию на другую конструкцию, то все-таки вынужден настаивать, что не ту )) скорее уж стандарт надо допилить
dots_rei через цикл проще, но не забудьте, что при использовании myisam update блокирует всю таблицу. если таблица большая и/или к ней идёт много обращений, лучше, наверное, использовать условные операторы и заблокировать таблицу один раз, чем запрашивать 30 блокировок... попробуйте так: [sql]update your_table set field3 = case when (field1,field2) = (1,2) then 3 when (field1,field2) = (2,3) then 4 ... else null end where (field1,field2) in ((1,2),(2,3),...,(30,31))[/sql]