DELIMITER $$ DROP PROCEDURE IF EXISTS `sp_test3` $$ CREATE PROCEDURE `sp_test3`() top:BEGIN -- 错误标记,当sql执行出错的时候,设置标记等于1。 DECLARE _err INT DEFAULT 0; DECLARE fname LONGTEXT DEFAULT ''; DECLARE msg LONGTEXT DEFAULT ''; -- 定义局部变量:判断是否完成和数量 DECLARE done BOOLEAN DEFAULT 0; -- 定义游标1 DECLARE cs1 CURSOR FOR SELECT CONCAT(first_name,'1') FROM stu; -- 定义游标2 DECLARE cs2 CURSOR FOR SELECT CONCAT(first_name,'2') FROM stu; -- 当fetch游标到了数据库表格最后一行的时候,设置done=1。 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; -- 错误标记处理,放到最后再声明,要放到游标后面。 -- 不然会报错:Variable or condition declaration after cursor or handler declaration DECLARE CONTINUE HANDLER FOR SQLEXCEPTION,SQLWARNING,NOT FOUND set _err=1; -- 在开始循环之前修改数据,循环会使用新数据。 -- UPDATE stu SET first_name=DATE_FORMAT(NOW(),'%Y-%m-%d %h:%i:%s') WHERE id=1; -- 打开游标 OPEN cs1; -- 每开始一个循环,重置循环结束标记。 SET done = 0; REPEAT -- FETCH 游标中的列必须要和INTO的列数量和类型一致。 -- 如果游标中没有新的可用行,即Fetch到空行,则立即设置done=1。 FETCH cs1 INTO fname; -- 执行逻辑前必须要判断标记,否则repeat会多一次循环。 IF(done = 0) THEN -- 处理FETCH到的数据 SET msg = CONCAT(msg,fname,'/'); END IF; -- 通过判断done来结束循环 UNTIL done END REPEAT; -- 关闭游标 CLOSE cs1; -- 游标2 OPEN cs2; SET done = 0; REPEAT FETCH cs2 INTO fname; IF(done = 0) THEN SET msg = CONCAT(msg,fname,'/'); END IF; UNTIL done END REPEAT; CLOSE cs2; SELECT msg; END $$ DELIMITER ;