drop procedure if exists  useCursor ;delimiter //
   
 /*建立 存储过程 create */ 
 CREATE PROCEDURE useCursor()
    BEGIN
    /*局部变量的定义 declare*/   declare done boolean default 0;
 declare o int ;         declare cur1 CURSOR FOR SELECT id FROM testprocedure.user ;         /*    mysql 不知道为什么用异常加入判断 ?          *    此请参考官方文档 20.2.11. 光标 光标           *        这把 游标 异常后 捕捉           *        并设置 循环使用 变量 tmpname 为 null 跳出循环。          */         declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
      /*开游标*/      OPEN cur1;repeat         /*游标向下走一步*/          FETCH cur1 INTO o;
 select o;
until done end repeat;
      CLOSE cur1;
END;
//
delimiter ;call useCursor();结果:mysql> call useCursor();
+------+
| o    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)+------+
| o    |
+------+
|    2 |
+------+
1 row in set (0.00 sec)+------+
| o    |
+------+
|    3 |
+------+
1 row in set (0.00 sec)+------+
| o    |
+------+
|    4 |
+------+
1 row in set (0.00 sec)+------+
| o    |
+------+
|    4 |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected, 1 warning (0.00 sec)
数据库一共4条记录。为什么多循环了一次呢?上面红色字体代码是不是有错误呢?请高手帮看一下。

解决方案 »

  1.   

    declare cur1 CURSOR FOR SELECT id FROM testprocedure.user ;declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;repeat      FETCH cur1 INTO o;
         select o;
    until done end repeat;帮解释一下这几句话运行过程,多谢。
      

  2.   

    DELIMITER $$DROP PROCEDURE IF EXISTS `useCursor`$$CREATE DEFINER=`root`@`localhost` PROCEDURE `useCursor`()
    BEGIN
        /*局部变量的定义 declare*/ 
         DECLARE done BOOLEAN DEFAULT 0;
         DECLARE o INT ;
             DECLARE cur1 CURSOR FOR SELECT id FROM testprocedure.user;
           
             
             DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
      
         OPEN cur1;
    REPEAT
           
             FETCH cur1 INTO o;
         SELECT o;
         FETCH cur1 INTO o;
       UNTIL done END REPEAT;
        
          CLOSE cur1;
    END$$DELIMITER ;
      

  3.   

    repeat
    /*游标向下走一步*/ 
    FETCH cur1 INTO o;
    select o;
    until done end repeat;
    你可以设想一下最后一条记录时。 把值赋给 o, 你的程序 select o 输出,此刻 done 为0 ,
    然后执行 repeat, 再执行 FETCH cur1 INTO o; 此时,已经没有记录,导致 done 为 1,o中的值仍是上次的值没有更新。 再执行 select o; 输出仍为上次的 o值。 until done end repeat; done 已被置为1,退出循环。
      

  4.   

    多谢。明白了。declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;能帮讲解一下这个语句吗?或是给提供一些资料。
      

  5.   

    mysql help:
    20.2.10.1. DECLARE条件
    DECLARE condition_name CONDITION FOR condition_value
     
    condition_value:
        SQLSTATE [VALUE] sqlstate_value
      | mysql_error_code
    这个语句指定需要特殊处理的条件。它将一个名字和指定的错误条件关联起来。这个名字可以随后被用在DECLARE HANDLER语句中。请参阅20.2.10.2节,“DECLARE处理程序”。 除了SQLSTATE值,也支持MySQL错误代码。 20.2.10.2. DECLARE处理程序
    DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
     
    handler_type:
        CONTINUE
      | EXIT
      | UNDO
     
    condition_value:
        SQLSTATE [VALUE] sqlstate_value
      | condition_name
      | SQLWARNING
      | NOT FOUND
      | SQLEXCEPTION
      | mysql_error_code
    这个语句指定每个可以处理一个或多个条件的处理程序。如果产生一个或多个条件,指定的语句被执行。 对一个CONTINUE处理程序,当前子程序的执行在执行处理程序语句之后继续。对于EXIT处理程序,当前BEGIN...END复合语句的执行被终止。UNDO 处理程序类型语句还不被支持。·         SQLWARNING是对所有以01开头的SQLSTATE代码的速记。·         NOT FOUND是对所有以02开头的SQLSTATE代码的速记。·         SQLEXCEPTION是对所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的速记。除了SQLSTATE值,MySQL错误代码也不被支持。
      

  6.   

    MySQL官方文档 http://dev.mysql.com/doc/refman/5.1/zh/index.html
      

  7.   

    2楼的不对呀。加一个判断就好了。repeat
    FETCH cur1 INTO o;
       if not done then
          select o;
       end if;
    until done end repeat;
    多谢大家。 结贴
      

  8.   


    声明当sql语句遇到02000这个错误的时候继续执行别的下面的sql