使用FETCH语句获取游标数据最后一行重复

  • 问题描述《MySQL必知必会》中的P179存储过程执行完成之后在新表中重复插入了一行。

  • 存储过程processorders(计算出orders表中每个订单的总金额并存入一张新表)
#创建一个存储过程用于计算出每个订单的总金额并存放在一张新表中
DELIMITER //
CREATE PROCEDURE processorders()
BEGIN
	#声明局部变量
	DECLARE done BOOLEAN DEFAULT 0;
	DECLARE o INT;
	DECLARE t DECIMAL(8,2);
	
	#声明游标
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	
	#声明异常处理,当sql状态为02000时,将done设置为1
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
	
	#创建一个新表用于存储结果
	CREATE TABLE IF NOT EXISTS ordertotals
	(order_num INT,
	total DECIMAL(8,2)
	
	);
	
	#打开游标
	OPEN ordernumbers;
	
	#循环插入所有行
	REPEAT
		#获得订单号,行内指针指向最后一行的下一行处时执行该语句会使得SQLSTATE='02000'
		#导致上方句柄处理执行使得done = 1
		FETCH ordernumbers INTO o;
		
		#计算出带税总金额,结果会返回给参数t,该存储过程在最下面
		CALL ordertotal(o,1,t);
		
		#将订单号和总金额插入表中
		INSERT INTO ordertotals(order_num,total)
		VALUES(o,t);
	UNTIL done #结束循环条件为done为非0
	END REPEAT;
	
	#关闭游标
	CLOSE ordernumbers;
END//

#执行查询语句
CALL processorders()//
  • 得到的结果

  • 问题分析:当游标内指针指向最后一行的下一行时,再次执行
    FETCH ordernumbers INTO o;

    该语句时,要取当前行并且指针下移一行,因为此时指针指的位置非合法行,所以取出行错误,导致上方句柄处理触发,使得done = 1,而此时o则没有被插入新数据,还是上一轮循环的旧数据(即最后一行的订单号),所以导致了最后一行重复插入了两次。

  • 解决方法:在FETCH语句执行后立即判断done是否被修改为1,若被修改为1,则不执行后面的插入代码了。上方存储过程代码修改为

DELIMITER //
CREATE PROCEDURE processorders()
BEGIN
	#声明局部变量
	DECLARE done BOOLEAN DEFAULT 0;
	DECLARE o INT;
	DECLARE t DECIMAL(8,2);
	
	#声明游标
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	
	#声明异常处理,当sql状态为02000时,将done设置为1
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
	
	#创建一个新表用于存储结果
	CREATE TABLE IF NOT EXISTS ordertotals
	(order_num INT,
	total DECIMAL(8,2)
	
	);
	
	#打开游标
	OPEN ordernumbers;
	
	#循环插入所有行
	REPEAT
		#获得订单号,行内指针指向最后一行的下一行处时执行该语句会使得SQLSTATE='02000'
		#导致上方句柄处理执行使得done = 1
		FETCH ordernumbers INTO o;
		IF !done THEN #修正的关键位置
		
		#计算出带税总金额,结果会返回给参数t,该存储过程在最下面
		CALL ordertotal(o,1,t);
		
		#将订单号和总金额插入表中
		INSERT INTO ordertotals(order_num,total)
		VALUES(o,t);
		END IF;
	UNTIL done 
	END REPEAT;
	
	#关闭游标
	CLOSE ordernumbers;
END//

再次查询ordertotals表结果为

参考资料:

  1. https://stackoverflow.com/questions/16900482/mysql-cursor-fetching-same-result-twice
  2. https://my.oschina.net/u/1383934/blog/667444  《mysql游标最后一行重复的问题

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值