MySQL执行包含循环的存储过程时提示Query was empty错误
错误成因
- 子查询返回空集触发报错:当
A_Request表中不存在id = incr的记录,或是当前incr对应的bId在B_ProductLine表中没有匹配记录时,UPDATE语句里的赋值子查询会返回空结果,触发MySQL的Query was empty报错。你单独测试SQL时一般指定了实际存在的id值,没有覆盖到缺数场景,因此不会触发报错。 - 嵌套子查询的作用域歧义:原代码中多层嵌套引用
A_Request表,存储过程运行时可能出现表别名优先级混淆,导致部分场景下匹配不到记录,返回空查询。 - 循环逻辑未做断号兼容:如果
A_Request的id不是从1到76连续分布,遇到断号的incr值时,UPDATE语句完全没有匹配行,直接触发空查询报错。
解决办法
修改后的完整存储过程如下:
DELIMITER $$ CREATE PROCEDURE updateA() BEGIN DECLARE incr INT DEFAULT 1; DECLARE current_bId INT; a_loop: LOOP -- 先校验当前id对应的记录是否存在 SELECT bId INTO current_bId FROM `A_Request` WHERE `id` = incr LIMIT 1; -- 不存在则直接跳过本轮循环 IF current_bId IS NULL THEN SET incr = incr + 1; IF incr = 77 THEN LEAVE a_loop; END IF; ITERATE a_loop; END IF; -- 执行更新,简化子查询消除歧义 UPDATE `A_Request` SET `requestRegion` = (SELECT GROUP_CONCAT( DISTINCT (CASE WHEN subRegion in (4,5) THEN 108 WHEN subRegion in (6,7) THEN 109 WHEN subRegion in (195,201) THEN 111 ELSE null END) SEPARATOR '; ' ) as `newRegion` FROM `B_ProductLine` where requestId = current_bId group by requestId) WHERE `id` = incr; SET incr = incr + 1; IF incr = 77 THEN LEAVE a_loop; END IF; END LOOP a_loop; END $$; DELIMITER ;
主要修改点:
- 新增记录存在性校验逻辑,不存在对应记录时直接跳过本轮循环,从根源避免空查询报错。
- 提取
bId为单独变量,简化嵌套子查询,消除表引用的作用域歧义。 - 如果业务需要空值场景下
requestRegion赋值为默认值,可以在GROUP_CONCAT外层套IFNULL()函数实现。
内容的提问来源于stack exchange,提问作者seph1119
相关产品推荐
相关产品推荐

