Не возможно обновить (UPDATE) ту же таблицу, которую используешь в SELECT-запросе

    Сегодня наткнулся на очень неприятный баг в MySQL. При выполнении следующего запроса в MySQL 5.0.45:

    UPDATE `files` SET `file_md5` =
    (
    SELECT MD5( `file_blob` )
    FROM `files`
    WHERE `id`= 6
    )
    WHERE `id` = 6

    Получил ошибку:
    #1093 — You can't specify target table 'files' for update in FROM clause

    Как выяснилось дело в баге номер 6980. В MySQL вы не можете изменять (в том числе и DELETE) ту же таблицу, которую используете в SELECT-запросе. Такое поведение задокументировано по адресу dev.mysql.com/doc/mysql/en/UPDATE.html. Баг был обнаружен еще в MySQL 4.1.7, но по сей день не исправлен.

    Один из выходов — использовать несколько запросов.

    Либо можно использовать временную таблицу во вложенном запросе:

    UPDATE `apples`
    SET `price` = (
    SELECT `price` FROM (
    SELECT * FROM `apples`
    ) AS x
    WHERE `variety` = 'gala')
    WHERE `variety` = 'fuji';

    Но данный метод очень некрасив и плохо сказывается на производительности. И, к сожалению, не будет работать если вы будете обращаться ко временной таблице больше одного раза…
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +17
      UPDATE files SET file_md5=MD5(file_blob) WHERE id=6
        +4
        +1. Именно так правильно делать, а автор топика написал глупый запрос. Оторвать руки и заставить читать документацию.
          0
          Ладно, признаю, что я неправильно составил запрос. Опыта работы с БД не хватает. Я почему-то подумал, что MD5() работает ТОЛЬКО с SELECT. Мне на самом деле надо было назначить MD5 почти всем файлам в таблице, а не только ID = 6…

          Как бы там ни было, описанный мною трюк работает и может быть при надобности использован.
          Главная цель моего поста была именно в этом.
            0
            если всем то UPDATE files SET file_md5=MD5(file_blob);
          +5
          Я не знаком с MySQL, но так не сработает?:
          UPDATE `files` SET `file_md5` = MD5( `file_blob` )
          WHERE `id` = 6
            +6
            Мне бы никогда в голову не пришла мысль решать задачу создания поля с MD5 так как делает автор.
            +3
            Извините но это не баг. Не всё, что присылают в багрепорт оказывается багом. По вашей ссылке вопрошающему вполне объяснили:
            Thank you for the report, but currently you can't update the same table which you use in
            the SELECT part.
            This behaviour is documented at:
            dev.mysql.com/doc/mysql/en/UPDATE.html

            «Спасибо за отчет, но в настоящее время вы не можете обновлять таблицу, которую используете в запросе SELECT. Это описано в документации.»

            То есть это поведение подразумевается и так сделано специально. И думаю, что и дальше так нельзя будет делать. (И я, если честно, считаю что это правильно)
              0
              на время выполнения селекта таблица лочится, что вполне логично и правильно, приведенный же запрос в посте ошибочен в своей сути, о чем и написал товарищ zed_0xff
                +3
                Это не баг, как вы себе представляете результат пиления сука, на котором сидите?
                  0
                  Запятую забыли…
                    +2
                    после «пиления»? :) я нарочно не поставил! :)
                  +3
                  обфускация sql?

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое