这是我在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
答案 0 :(得分:0)
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 值所得的结果明显不同。
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或与当前分配的值不同的值的行呢?我们是否担心更新这些行?