fetch在获取集合最后一行后,再获取一次才会触发02000,这样会导致循坏多进行一次,虽然集合已经到末尾,虽然fetch失败,但其他语句仍然会进行,获取的内容和上一次相同。
因此在fetch后应该马上进行标志符判断,有两种做法:一个是fetch完之后做if判断,一个是在repeat前先进行一次fetch,循坏体内fetch放到最后。
DELIMITER @@
CREATE PROCEDURE processsalary()
BEGIN
DECLARE `max` DOUBLE(10,2);
DECLARE `min` DOUBLE(10,2);
DECLARE `avg` DOUBLE(10,2);
DECLARE id INT;
DECLARE done BOOLEAN DEFAULT 0;
DECLARE line CURSOR FOR
SELECT DISTINCT department_id
FROM employees
-- order by department_id
;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
CREATE TABLE IF NOT EXISTS departsalary
(depart_id INT,`max` DOUBLE(10,2),`min` DOUBLE(10,2),`avg` DOUBLE(10,2));
OPEN line;
IF 0 THEN
REPEAT
FETCH line INTO id;#不在fetch后加判断会重复输出最后一行
IF done=0 THEN #获取后马上判断标识符
CALL departmentsalary(id,`max`,`min`,`avg`);
INSERT INTO departsalary (depart_id ,`max` ,`min` ,`avg` )
VALUES (id,`max`,`min`,`avg`);
END IF;
UNTIL done END REPEAT ;
ELSE #方法2,先从集合获取一次再进行循环获取,这样fetch语句结束后能马上进行结束条件的判断
FETCH line INTO id;
REPEAT
CALL departmentsalary(id,`max`,`min`,`avg`);
INSERT INTO departsalary (depart_id ,`max` ,`min` ,`avg` )
VALUES (id,`max`,`min`,`avg`);
FETCH line INTO id; #循坏体内fetch放到最后
UNTIL done END REPEAT ;
END IF;
CLOSE line;
END@@
DELIMITER ;