Ошибка выполнения процедуры 1221 - Неправильное использование UPDATE и LIMIT - PullRequest
0 голосов
/ 25 июня 2019

Это моя первая хранимая процедура в базе данных MySQL.

Мне нужно обновить тысячи строк, и при традиционном запросе SQL база данных потерпела крах.

Я думал обновить эти тысячи строк, используя ограничениесинтаксис, но у меня ошибка следующая:

Ошибка выполнения процедуры 1221 - Неправильное использование UPDATE и LIMIT

Можете ли вы мне помочь?

BEGIN

REPEAT

    UPDATE `tbl_01` jjj
    JOIN (
        SELECT
            t1.idticket,
            MAX(t1.ass) AS date_hour_ass
        FROM
            tbl_02 t1
        GROUP BY
            t1.idticket
    ) AS kkk
    SET jjj.date_hour_ass = STR_TO_DATE(
        kkk.date_hour_ass,
        '%d/%m/%Y %H:%i'
    )
    WHERE
        jjj.date_hour_ass IS NULL
    AND jjj.idticket = kkk.idticket LIMIT 100000;

    UNTIL ROW_COUNT() = 0 END REPEAT;

    END

1 Ответ

0 голосов
/ 25 июня 2019

Справочное руководство по MySQL документирует это ограничение для оператора UPDATE.

https://dev.mysql.com/doc/refman/8.0/en/update.html

выдержка:

Для синтаксиса нескольких таблиц, ORDER BY и LIMIT нельзя использовать.


Один из возможных путей обхода - избежать объединения и использовать коррелированный подзапрос.Это не оптимально с точки зрения производительности, но производительность должна быть предсказуемой с подходящим доступным индексом

... ON `tbl_02` (`idticket`,`ass`)

Немного странно, что мы получаем максимальное значение строки, ожидая значение даты, представленное в формате dd/mm/yyyy.

По сравнению со строковыми значениями '30/03/2019' больше '25/06/2019'.Это значительно отличается от результата, который мы получили бы при сравнении значений date .

25 июня ('2019-06-25') "больше, чем" 3 марта 2019 ('2019-03-30')

Может быть, это то, что мы хотим, наибольшее строковое значение, сравнивающее значение дня сначала, перед сравнением месяца, с ведущими нулями или без них.Я не знаю, чего мы пытаемся достичь.Я предполагаю, что нам на самом деле может потребоваться максимальное значение даты, но это всего лишь предположение.

  UPDATE `tbl_01` t
     SET t.date_hour_ass = ( SELECT MAX(STR_TO_DATE(s.ass,'%d/%m/%Y %H:%i'))
                               FROM `tbl_02` s
                              WHERE s.idticket = t.idticket
                           )
   WHERE t.date_hour_ass IS NULL
   LIMIT 100000 

Обратите внимание, что предложение LIMIT является ограничением на количество совпадающих строк, а не количествомстроки изменились.Мы не видим никакой гарантии того, что в tbl_01 не будет строк, которые не будут иметь значения NULL, даже после того, как инструкция UPDATE обработает их.например, в tbl_02 не может быть совпадающих строк, поэтому подзапрос возвращает NULL.

Таким образом, существует вероятность того, что этот оператор будет соответствовать 100 000 строк и изменить нулевые строки, поэтому ROWS_AFFECTED() может вернуть 0, даже если строк большев tbl_01 это может быть обновлено.

Ужасное исправление этого будет включать условие для того же подзапроса в предложении WHERE.

  UPDATE `tbl_01` t
     SET t.date_hour_ass = ( SELECT MAX(STR_TO_DATE(s.ass,'%d/%m/%Y %H:%i'))
                               FROM `tbl_02` s
                              WHERE s.idticket = t.idticket
                           )
   WHERE t.date_hour_ass IS NULL
     AND
                           ( SELECT MAX(STR_TO_DATE(s.ass,'%d/%m/%Y %H:%i'))
                               FROM `tbl_02` s
                              WHERE s.idticket = t.idticket
                           )
         IS NOT NULL
   LIMIT 100000

Как насчет строк в tbl_01которые имеют ненулевое значение для date_hour_ass, но подзапрос возвратит NULL или значение, отличное от назначенного в настоящее время?Мы вообще обеспокоены обновлением этих строк?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...