我在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次,等等。有什么想法发生在这里吗?
答案 0 :(得分:22)
当not_found_creadit = 1
没有返回任何行时,会触发设置FETCH
的处理程序,但是在执行FETCH
之前检查其值,所以当FETCH
失败时,循环的主体将执行一次额外的时间,然后循环循环在 next 迭代开始时退出。
重新排列代码,以便在 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
答案 1 :(得分:-1)
你必须纠正类型,因为我写了默认(我不知道你有什么表信用)。结束如果U创建表TempTable使用
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 $$