MySQL嵌套游标循环、动态游标

表结构:

 

表数据:


 

期望结果:


 虽然这种结果可以通过MySQL中的GROUP_CONCAT函数实现,但是此函数有字节长度限制

SELECT ROW_ID, CAST(CONCAT('[', GROUP_CONCAT('{\'FIELD_ID\'', ' : ', IF(INSTR(VALUE, '[{') = 0, CONCAT('\'', VALUE, '\''), VALUE), '}'), ']') AS BINARY) FROM T_TASK_DATA GROUP BY ROW_ID

 

DELIMITER $$
USE `mpp_master_data`$$
DROP PROCEDURE IF EXISTS `SP_QUERY_TASK_DATA`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_QUERY_TASK_DATA`()
BEGIN
	DECLARE V_FIG INT DEFAULT 0;
	DECLARE V_ROW_ID INT;
	DECLARE V_FIELD_ID INT;
	DECLARE V_FIELD_VALUE VARCHAR(10240);
	
 	DECLARE V_CRS_TASK_DATA CURSOR FOR SELECT DISTINCT ROW_ID AS V_ROW_ID FROM T_TASK_DATA LIMIT 0, 200;
 	DECLARE V_CRS_FIELD_DATA CURSOR FOR SELECT FIELD_ID AS V_FIELD_ID, VALUE AS V_FIELD_VALUE FROM T_TASK_DATA WHERE ROW_ID=V_ROW_ID ORDER BY FIELD_ID ASC;
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET V_FIG = 1;
	
	-- 创建临时表
	DROP TABLE IF EXISTS TMP_TASK_ROW_DATA;
	CREATE TEMPORARY TABLE TMP_TASK_ROW_DATA(ROW_ID INT(10), VALUE VARCHAR(10240), PRIMARY KEY (`ROW_ID`));
	
	-- 打开第一层游标,进行遍历
	OPEN V_CRS_TASK_DATA;
	ROW_LOOP: LOOP
	  FETCH V_CRS_TASK_DATA INTO V_ROW_ID;
	  IF V_FIG = 1 THEN
	    LEAVE ROW_LOOP;
	  END IF;
	  
	  SET @V_VALUE = '';
	  
	  -- 打开第二层游标,进程遍历
	  OPEN V_CRS_FIELD_DATA;
	  FIELD_LOOP: LOOP
	    FETCH V_CRS_FIELD_DATA INTO V_FIELD_ID, V_FIELD_VALUE;
	    IF V_FIG = 1 THEN
	      LEAVE FIELD_LOOP;
	    END IF;
	    
	    SET @V_VALUE = CONCAT(@V_VALUE, CONCAT(',{"FIELD_ID": ', V_FIELD_ID, ', "VALUE": "', IFNULL(V_FIELD_VALUE, '') ,'"}'));
	  END LOOP FIELD_LOOP;
	  CLOSE V_CRS_FIELD_DATA;
	  SET V_FIG = 0;
	  
	  SET @V_VALUE = SUBSTRING(@V_VALUE, 2);
	  SET @V_VALUE = REPLACE(@V_VALUE, '"', '#');
	  SET @V_VALUE = REPLACE(@V_VALUE, '\'', '$');
	  
	  SET @V_SQL = CONCAT('INSERT INTO TMP_TASK_ROW_DATA(ROW_ID, VALUE) VALUES (', V_ROW_ID, ', \'[', @V_VALUE, ']\');');
	  -- SELECT V_ROW_ID, @V_VALUE, @V_SQL; 
	  
	  PREPARE MAIN_STMT FROM @V_SQL;
	  EXECUTE MAIN_STMT;
	  DEALLOCATE PREPARE MAIN_STMT;
	  
	END LOOP ROW_LOOP;
	CLOSE V_CRS_TASK_DATA;  
	
	SELECT * FROM TMP_TASK_ROW_DATA;
	DROP TABLE TMP_TASK_ROW_DATA;
  END$$
DELIMITER ;

 

 

以上第二个游标属于模拟动态,

第二种方式:

MySQL本身是不支持动态游标的,但可以通过(准备语句+视图+静态游标)的方法来近似实现。 

参考:

http://suwish.com/html/mysql-dynamic-cursor.html

http://blog.csdn.net/wzy0623/article/details/8619253

 

说明:

http://blog.csdn.net/zengmuansha/article/details/5516924

游标循环 查询和更新是很慢的一件事情  

第一层层循环200  

第二层循环最大15  

执行拼接的SQL插入数据到临时表

总共耗时21秒左右,两层循环耗时16秒左右  

猜你喜欢

转载自singhoo.iteye.com/blog/1997226
今日推荐