过程执行失败1221-错误使用UPDATE和LIMIT

时间:2019-06-25 15:05:25

标签: mysql stored-procedures

这是我在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 :(得分:0)

MySQL参考手册记录了对UPDATE语句的限制。

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

节选:

  

对于多表语法,不能使用ORDER BYLIMIT


一种可能的解决方法是避免连接,并使用相关的子查询。从性能的角度来看,这并不是最佳选择,但是使用适当的可用索引,应该可以预测性能

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

奇怪的是,我们正在获取字符串的最大值,并期望以dd/mm/yyyy格式表示的日期值。

与字符串值相比,'30/03/2019'大于'25/06/2019'。这与我们比较 date 值所得的结果明显不同。

6月25日('2019-06-25')“大于” 2019年3月3日('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子句是对匹配的行数的限制,而不是更改的行数。我们没有看到任何保证,即使在UPDATE语句处理完之后,tbl_01中也不会有没有NULL值的行。例如tbl_02中可能没有匹配的行,因此子查询返回NULL。

因此该语句有可能匹配100,000行并更改了零行,因此即使ROWS_AFFECTED()中有更多行可以更新,tbl_01也会返回0。

对此的一个难看的解决方法是在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值但子查询将返回NULL或与当前分配的值不同的值的行呢?我们是否担心更新这些行?