Цикл курсора MYSQL, запускает один дополнительный раунд, почему?
Я перебираю результат набора курсора в хранимой процедуре 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 Если U create table 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 $$