MYSQL游标循环,运行一个额外的回合,为什么?

时间:2012-09-06 00:43:27

标签: mysql loops stored-procedures cursor

我在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次,等等。有什么想法发生在这里吗?

2 个答案:

答案 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 $$