<rmcreative>

RSS

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

11 марта 2009

Сразу предупреждаю, что эффективней использовать несколько «классических» запросов и, по возможности, транзакции (которые MyISAM не поддерживает). Так что… для общего развития:

Способ №1

UPDATE tbl_country SET price = CASE
WHEN code = 1 THEN 123;
WHEN code = 2 THEN 456;
…
END
WHERE code IN (1,2,…)

Способ №2

INSERT INTO tbl_country
(code, price)
VALUES
(1, 123),
(2, 456),
…
ON DUPLICATE KEY UPDATE tbl_country.price = VALUES(price);

Комментарии RSS

  1. №1358
    aktuba
    aktuba 11.03.2009, 2:46:38

    Лучше бы ты INSERT ON DUPLICATE KEY показал ;)

  2. №1359
    dohlik
    dohlik 11.03.2009, 9:34:10

    Тогда уж REPLACE наверное :)

  3. №1360
    zw0rk
    zw0rk 11.03.2009, 10:49:20

    Сам-то пробовал свой запрос? Он все неверные записи, для которых CASE твой не выполнился NULL-ом заполнит. Советчик, блин. ОБЯЗАТЕЛЬНО необходимо сделать ELSE code.

  4. №1361
    Sam
    Sam 11.03.2009, 12:07:52

    aktuba

    Способ №2 не оно?

    zw0rk

    Внимательнее надо быть… там как-бы WHERE IN имеется.

  5. №1362
    CharnaD
    CharnaD 11.03.2009, 13:20:31

    Почему несколько запросов быстрее чем один?

  6. №1363
    zw0rk
    zw0rk 11.03.2009, 13:54:59

    И что? Откуда уверенность, что все записи обладают нужным code?

  7. №1364
    Sam
    Sam 11.03.2009, 14:30:50

    zw0rk

    Нашёл ошибочку у себя. Поправил: WHERE id IN на WHERE code IN. Скорее всего это вас и озадачило… и верно озадачило.

    CharnaD

    Из за CASE. Я проверял, если что…

  8. №1366
    Денис Радченко
    Денис Радченко 12.03.2009, 0:05:03

    Спасибо, даже не знал про эти трюки :)

  9. №2880
    ARACOOL
    ARACOOL 14.08.2010, 13:55:13

    Я примерно помнил как работать с IN(), ваша статья помогла окончательно вспомнить!

  10. №3314
    Buzzman
    Buzzman 28.10.2010, 22:59:49

    А что будет работать быстрее 1 запрос с 100 условий, или 100 запросов? Мне нужно сделать UPDATE у > 100 записей наиболее быстрым способом.

  11. №3316
    Sam
    Sam 28.10.2010, 23:04:24

    Смотря какой запрос.

  12. №3318
    Buzzman
    Buzzman 28.10.2010, 23:33:14

    Ну запрос я уже создал. Работает пока для малого кол-ва записей. А вот на большом кол-ве пока не проверял.

    Смотря какой

    Такой, чтобы обновлял в каждой записи одно целочисленное поле, зная id записи этой.

  13. №5713
    Chumodan
    Chumodan 27.12.2011, 0:38:52

    Spasibo! Kratko, ponjatno i polezno!

  14. №6370
    Gtvar
    Gtvar 21.06.2012, 16:53:57

    zw0rk имел ввиду не это, а то что нужно в этом запросе поставить перед END ELSE price иначе обнулит те значения где code не равно ни единице ни двойке.

  15. №6697
    Александр
    Александр 20.09.2012, 0:34:17

    Спасибо за способы. Вопрос: можно ли в 1-м варианте применить несколько критериев WHERE? Мне нужно ... AND manual_price = '0';

  16. №6698
    Александр
    Александр 20.09.2012, 0:38:10

    эффективней использовать несколько «классических» запросов

    Ага. Куда уж эффективней. 13к полей с "классикой" обновляются у меня минут 7, а единым запросом - менее полуминуты.

  17. №6702
    Sam
    Sam 20.09.2012, 12:20:32

    Александр, можно.

  18. №6706
    Александр
    Александр 20.09.2012, 14:33:00

    Спасибо, и еще вопрос - чем ограничивается длина запроса? my.cnf?

  19. №6712
    Sam
    Sam 20.09.2012, 16:04:30

    Размером пакета. Настраивается в my.cnf.

  20. №6894
    fad
    fad 23.10.2012, 23:01:39

    точки с запятой в запросе не нужны

  21. №7552
    vit
    vit 19.02.2013, 14:37:44

    Спасибо! Первый пример очень помог!

  22. №8432
    Trey
    Trey 08.10.2013, 20:17:27

    I wonder how I missed this. The first method is right. Thanks - Trey

  23. №9013
    Аскар
    Аскар 15.05.2014, 11:27:16

    Пример ещё одного варианта того же CASE

    DROP TABLE IF EXISTS `test`;
    CREATE TABLE `test` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `price` int(11) NOT NULL,
      `title` varchar(255) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    INSERT INTO `test` VALUES ('1', '10', 'new q');
    INSERT INTO `test` VALUES ('2', '20', 'new w');
    INSERT INTO `test` VALUES ('3', '3', 'new r');
    UPDATE `test`
    SET
    `price` =  CASE
        WHEN `id`=1 THEN 10
        WHEN `id`=2 THEN 20
    ELSE `price` END,
    `title` = CASE
        WHEN `id`=1 THEN 'new q'
        WHEN `id`=2 THEN 'new w'
        WHEN `id`=3 THEN 'new r'
    ELSE `title` END
    WHERE `id` IN (1,2,3)
  24. №9461
    Zeemo
    Zeemo 04.12.2014, 13:07:31

    I think first method is correct.

  25. №10138
    ДМ
    ДМ 23.12.2015, 22:15:54

    UPDATE ttt st SET st.status = CASE WHEN Now() > st.ttd AND st.status in (0, 1, 2) THEN 3 END WHEN Now() BETWEEN st.tfd AND st.ttd and st.status in (0, 1, 3) THEN 2 END WHEN Now() < st.tfd and st.status in (1, 2, 3) THEN 0 END ELSE st.status END CASE WHERE st.status != 4

    Что не так?

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.