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.****.net/wzy0623/article/details/8619253
说明:
http://blog.****.net/zengmuansha/article/details/5516924
游标循环 查询和更新是很慢的一件事情
第一层层循环200
第二层循环最大15
执行拼接的SQL插入数据到临时表
总共耗时21秒左右,两层循环耗时16秒左右