MYSQL游标循环,多跑一圈,为啥?
Posted
技术标签:
【中文标题】MYSQL游标循环,多跑一圈,为啥?【英文标题】:MYSQL cursor loop, runs one extra round, why?MYSQL游标循环,多跑一圈,为什么? 【发布时间】:2012-08-30 18:30:30 【问题描述】:我正在循环访问 mysql 存储过程中的游标结果集。我面临一个问题,即循环总是运行两次最后一条记录。这是我的代码,
BEGIN
DECLARE not_found_creadit INT DEFAULT 0;
DECLARE cur_credit CURSOR FOR
SELECT customer_id, amount, status, user_type, employee, note FROM credit WHERE status = 'approved' AND customer_id = int_cust_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found_creadit = 1;
OPEN cur_credit;
SET not_found_creadit = 0;
credit_loop : LOOP
IF not_found_creadit THEN
CLOSE cur_credit;
LEAVE credit_loop;
END IF;
FETCH cur_credit INTO vc_customer, dec_amount, vc_status, vc_user_type, vc_emp, vc_note;
SELECT vc_customer, dec_amount, vc_status, vc_user_type, vc_emp, vc_note;
......
......
END LOOP;
END;
表示如果我有 3 条记录,循环运行 4 次,如果是 10 条记录,则循环运行 11 次,等等。知道这里发生了什么吗?
【问题讨论】:
【参考方案1】:设置not_found_creadit = 1
的处理程序在FETCH
没有返回任何行时被触发,但是您在执行FETCH
之前检查它的值,因此循环的主体将当FETCH
失败时额外执行一次,然后循环循环在下一次 迭代开始时退出。
重新排列您的代码以在FETCH
之后立即检查变量的值:
credit_loop : LOOP
FETCH cur_credit INTO vc_customer, dec_amount, vc_status, vc_user_type, vc_emp, vc_note;
IF not_found_creadit THEN
CLOSE cur_credit;
LEAVE credit_loop;
END IF;
SELECT vc_customer, dec_amount, vc_status, vc_user_type, vc_emp, vc_note;
......
......
END LOOP;
另外,考虑将变量的拼写更正为not_found_credit
【讨论】:
【参考方案2】:你必须正确的类型,因为我写的是默认值(我不知道你在表信用中有什么)。 End If U create table TempTable use
TRUNCATE TempTable;
请重写示例
CREATE CREATE TEMPORARY TABLE TempTable (`Id` int(11) NOT NULL auto_increment,
`customer_id` int(11) NOT NULL,
`amount` int(11) NOT NULL,
`status` varchar(1000) NOT NULL,
`user_type` int(11) NOT NULL default '0',
`employee` varchar(1000) NOT NULL,
PRIMARY KEY (`customer_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci AUTO_INCREMENT=1 ;");
当然类型不好:)
DELIMITER $$
DROP PROCEDURE IF EXISTS CursorX $$
CREATE PROCEDURE `CursorX`()
BEGIN
DECLARE xCustomerId int(11);
DECLARE xStatus int(11);
DECLARE xUserType varchar(255);
DECLARE xEmployee varchar(255);
DECLARE xNote varchar(255);
DECLARE i int(11);
DECLARE recordNotFound INTEGER DEFAULT 0;
DECLARE cur_credit CURSOR FOR SELECT customer_id, amount, status, user_type, employee, note FROM credit WHERE status = 'approved' AND customer_id = int_cust_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET recordNotFound = 1;
DROP TEMPORARY TABLE IF EXISTS TempTable;
CREATE TEMPORARY TABLE TempTable AS(SELECT * FROM credit);
OPEN cur_credit;
set not_found_creadit = 0;
credit_loop: LOOP
SET i = i +1;
FETCH cur_credit INTO xCustomerId,xStatus,xUserType,xEmployee,xNote;
IF not_found_creadit THEN
LEAVE credit_loop;
END IF;
END LOOP credit_loop;
CLOSE cur_credit;
select * FROM TempTable;
END $$
【讨论】:
以上是关于MYSQL游标循环,多跑一圈,为啥?的主要内容,如果未能解决你的问题,请参考以下文章