За последние 24 часа нас посетили 23913 программистов и 1553 робота. Сейчас ищут 996 программистов ...

Множественный UPDATE

Тема в разделе "PHP и базы данных", создана пользователем dots_rei, 10 сен 2010.

  1. dots_rei

    dots_rei Активный пользователь

    С нами с:
    7 авг 2009
    Сообщения:
    193
    Симпатии:
    0
    Всем доброго времени суток!

    Возникла задача обновления ~30 строк в одной таблице.
    Что лучше использовать: загнать апдейты в цикл или использовать конструкцию update case?
    как это отразится на работоспособности?

    Заранее спасибо за ответы :)
     
  2. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    в зависимости от того, как часто надо обновлять столько строк.
    если нечасто, то можно реализовать в цикле.
    если же часто - можно сделать в виде триггера на вставку,
    и делать всё одним запросом в виде вставки,
    а уже триггер будет проверять - если такая строка имеется,
    то обновить значения, если же нет - создать.

    если обновляется поле булевого типа (вкл/выкл),
    то можно реализовать обновление всего одним запросом типа
    UPDATE table SET enabled=False WHERE id IN(0, 1, 2, 3...)

    вообще вариантов много, зависит от того, что КОНКРЕТНО нужно сделать
     
  3. ShamahN

    ShamahN Активный пользователь

    С нами с:
    10 апр 2007
    Сообщения:
    1.449
    Симпатии:
    0
    Адрес:
    г.Волгодонск Роствской обл.
    insert on duplicate update =)
     
  4. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    уж легче тогда REPLACE, но к сожалению данная команда поддерживается только MySQL.
    PostgreSQL не поддерживает, насчёт Майкрософтовской БД - не знаю,
    но тоже врядли поддерживается, т.к. эта конструкция не является стандартом (а жаль, очень хорошая штука).

    А вот триггеры поддерживаются уже почти везде (разве только в sqlite нету :-D )

    Если нам надо обновить всего одно поле? То тут уже REPLACE/ON DUPICATE UPDATE не поможет.
    Например, у нас три поля, а обновляются только два - их-то мы и посылаем команде обновить.
    Replace при дублирующемся первичном ключе удаляет старую строку, и вставляет новую.
    В итогде значение первого поля будет NULL, т.к. это поле мы не посылаем, а старое значение будет утеряно.

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

    dots_rei Активный пользователь

    С нами с:
    7 авг 2009
    Сообщения:
    193
    Симпатии:
    0
    Используется MySQL, myisam. В таблице 3 поля, одно из них обновляется (число) в зависимости от других двух.
    Обновляться данные будут нечасто, сделала через цикл.

    Gromo, спасибо :)
     
  6. ShamahN

    ShamahN Активный пользователь

    С нами с:
    10 апр 2007
    Сообщения:
    1.449
    Симпатии:
    0
    Адрес:
    г.Волгодонск Роствской обл.
    чет не сталкивался с таким. В доке что-то подобное читал, но, на самом деле проблем не было никогда. Очень гибкий и удобный механизм. Только обновляемые, при совпадении ключа(ей) поля обновляются и ничего не теряется =) проверял. Хотя, это, наверное, из-за того, что ты делаешь инсерт, (и только при существовании ключей делаешь апдейт) и следовательно, значения всех полей у тебя есть ;)
    Это если известно, что запись с ключом уже есть. Если сравнивать с insert on duplicate update - предварительно делать запрос на существование записи с ключом. Вариант с REPLACE будет медленнее ;)
     
  7. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    исходя из той документации, что я читал, предварительная запись удаляется.
    может быть сейчас это и не так, но стоит это иметь в виду.

    REPLACE и ON DUPLICATE UPDATE - это просто разные названия для одной и той же инструкции,
    так что по скорости разницы быть не должно.
     
  8. trashcan

    trashcan Активный пользователь

    С нами с:
    30 сен 2010
    Сообщения:
    3
    Симпатии:
    0
    Поздновато, но не могу пройти мимо, ради тех, кто придет после меня ))
    Не легче.

    Не стоит )) Вы не ту документацию читали - так, как говорите вы, не было никогда.

    INSERT ... ON DUPLICATE KEY UPDATE запись не удаляет, он обновляет ее при совпадении ключей,
    причем исключительно поля, указанные после слова UPDATE

    Посему претензии вроде
    актуальны только для REPLACE.

    Поэтому и по скорости отнюдь не то же самое, так как REPLACE при совпадении ключей делает DELETE, затем INSERT,
    а INSERT ... ON DUPLICATE KEY UPDATE ограничивается одним только UPDATE'ом.

    Так что это не
    совсем не просто ))
     
  9. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    trashcan
    спасибо, просветили.

    я читал ту самую официальную документацию.
    просто был неправ в том, что replace и on duplicate update - это одна и та же конструкция.

    теперь осталось допилить эту (точнее, эти) конструкцию до стандарта
    (чтобы и postgresql поддерживалось) и будет вообще кошерно.
     
  10. trashcan

    trashcan Активный пользователь

    С нами с:
    30 сен 2010
    Сообщения:
    3
    Симпатии:
    0
    если вы читали документацию на другую конструкцию, то все-таки вынужден настаивать, что не ту ))

    :p

    скорее уж стандарт надо допилить
     
  11. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    trashcan
    похоже, что ты любитель всё осложнять :)
     
  12. trashcan

    trashcan Активный пользователь

    С нами с:
    30 сен 2010
    Сообщения:
    3
    Симпатии:
    0
    И это говорит человек, предлагавший использовать триггеры ;)
     
  13. stas_t

    stas_t Активный пользователь

    С нами с:
    24 апр 2007
    Сообщения:
    500
    Симпатии:
    0
    Адрес:
    Courbevoie, France
    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]