如何用EXECUTE语句更新表?存储过程报错排查
问题分析与解决方案
首先,我们先明确你的核心需求:将QUADRI表中各数据列(排除ID)的总和,更新到CELLE表对应CELLANAME的NEEDED字段中。接下来我们逐一分析你遇到的错误,并给出可行的解决办法。
你遇到的两个错误原因
第一个存储过程(带参数的版本)
报错ERROR 1210. Incorrect arguments to EXECUTE的原因有两个:
- 动态SQL里有两个占位符(
sum(?)和cellaname=?),但你执行时只传了一个参数@NC,参数数量不匹配; - 更关键的是:MySQL预处理语句的占位符只能代替值,不能代替列名/表名这类标识符,
sum(?)里的?无法识别为列名,所以这种写法从根本上就行不通。
第二个存储过程(游标遍历版本)
报错Cursor is not open的直接原因是你声明游标后,没有调用OPEN col_names;就直接执行FETCH操作。除此之外还有两个隐藏问题:
WHERE table_name = quadri里的quadri是表名,需要加单引号写成'quadri';update celle set needed=sum(col_name)...中的sum(col_name)会把变量col_name当成字符串(比如'SBR_750'),而不是实际的列名,无法计算正确的总和,必须用动态SQL来处理。
正确的存储过程实现
下面是修正后的游标遍历版本存储过程,解决了所有上述问题:
CREATE DEFINER=`root`@`%.zamberlan.local` PROCEDURE `AggiornaCelle`() BEGIN DECLARE done BOOLEAN DEFAULT FALSE; DECLARE col_name VARCHAR(20); -- 声明游标:获取QUADRI表中除ID外的所有数据列名 DECLARE col_names CURSOR FOR SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'quadri' AND column_name != 'ID' -- 排除不需要的ID列 ORDER BY ordinal_position; -- 声明异常处理:游标遍历结束时标记完成状态 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 打开游标(解决"Cursor is not open"错误) OPEN col_names; -- 遍历所有列名 the_loop: LOOP FETCH col_names INTO col_name; -- 遍历完成则退出循环 IF done THEN LEAVE the_loop; END IF; -- 构建动态SQL:拼接列名,计算对应列的总和并更新CELLE表 SET @sql = CONCAT( 'UPDATE celle ', 'SET needed = (SELECT SUM(', col_name, ') FROM quadri) ', 'WHERE cellaname = ''', col_name, '''' ); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP the_loop; -- 关闭游标 CLOSE col_names; END
关键优化点说明
- 添加了游标遍历结束的异常处理,避免无限循环;
- 明确打开/关闭游标,解决游标未打开的错误;
- 排除了
ID列,只处理需要统计的数据列; - 通过
CONCAT拼接动态SQL,确保列名被正确识别为数据库标识符。
更简洁的非存储过程方案
如果QUADRI表的列不会频繁变动,你可以直接用一条SQL语句完成更新,无需存储过程,效率更高:
UPDATE celle c JOIN ( SELECT 'SBR_750' AS cellaname, SUM(SBR_750) AS needed FROM quadri UNION ALL SELECT 'b10C' AS cellaname, SUM(b10C) AS needed FROM quadri UNION ALL SELECT 'TGI' AS cellaname, SUM(TGI) AS needed FROM quadri ) q ON c.cellaname = q.cellaname SET c.needed = q.needed;
这个方法通过UNION ALL把各列的总和查询出来,再关联CELLE表完成批量更新,逻辑更直观。
内容的提问来源于stack exchange,提问作者Massimo Griffani
相关产品推荐
相关产品推荐

