Skip to content

Instantly share code, notes, and snippets.

@geosmart
Last active March 8, 2016 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geosmart/c3d7f4eb0d9ad53751d7 to your computer and use it in GitHub Desktop.
Save geosmart/c3d7f4eb0d9ad53751d7 to your computer and use it in GitHub Desktop.
Why MySQL nested Cursor fetch always return the Parent Cursor's first values?
CREATE DEFINER = 'geocodingdb'@'%'
PROCEDURE geocodingdb.updateMatchResult()
BEGIN
DECLARE done1 int default false;
DECLARE bizId nvarchar(64);
# 定义光标 where source_address_id='001A866D0F5647B5A74530EF8CF8AAFA'
DECLARE cursor_bizId CURSOR FOR
select source_address_id FROM geocodingdb.MatchedAddressGroupbySkeleton
where source_address_id IN ('001A866D0F5647B5A74530EF8CF8AAFA','000032E78F5E4F65A2C75DAEAF53B62E') GROUP BY source_address_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = TRUE;
/* 打开光标 */
OPEN cursor_bizId;
# 循环获取业务ID
loop_getBizId:LOOP
FETCH cursor_bizId INTO bizId;
IF done1 THEN
LEAVE loop_getBizId;
/*关闭光标*/
CLOSE cursor_bizId;
END IF;
# 根据业务ID获取匹配地址
block_matchedAddress:BEGIN
DECLARE _rownum int;
DECLARE _matchID nvarchar(64);
DECLARE _matchedType nvarchar(8);
DECLARE _matchedAddress nvarchar(3000);
DECLARE _x,_y decimal(11, 6);
DECLARE done2 int default false;
#cursor:获取匹配地址(由于是动态select语句,故从视图中间接查询)
DECLARE cursor_matchedAddress CURSOR FOR SELECT * FROM temp_matchedAddress;
DECLARE continue handler for not found set done2 = true;
#新建视图temp_maxAddressNodeOrder存储 匹配地址中最深地址路径
SET @sql_query_maxAddressNodeOrder= CONCAT("(SELECT MAX(o1.AddressNodeOrder) AS deepSize, matched_address_type FROM MatchedAddressGroupbySkeleton t1 LEFT JOIN AddressNodeOrder o1 ON t1.matched_address_type = o1.addressNode
WHERE source_address_id='",bizId COLLATE utf8_unicode_ci ,"')");
SET @query_maxAddressNodeOrder = CONCAT('CREATE OR REPLACE view temp_maxAddressNodeOrder as ', @sql_query_maxAddressNodeOrder);
PREPARE stmt from @query_maxAddressNodeOrder;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
#新建视图temp_maxAddressNodeOrder存储 匹配地址(多个)
SET @temp_rowNumber=0;
SET @sql_query_matchedAddress= concat("SELECT getRowNum() AS _rownum, matched_address_id AS _matchID, matched_address_type AS _matchedType, matched_address AS _matchedAddress, longitude AS _x, latitude AS _y
FROM MatchedAddressGroupbySkeleton t3 WHERE t3.source_address_id='",bizId COLLATE utf8_unicode_ci ,"' AND t3.matched_address_type =
(SELECT matched_address_type FROM temp_maxAddressNodeOrder AS t2)");
SET @query_matchedAddress = CONCAT('CREATE OR REPLACE view temp_matchedAddress as ', @sql_query_matchedAddress);
PREPARE stmt from @query_matchedAddress;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
OPEN cursor_matchedAddress;
# 循环获取匹配地址
loop_getMatchedAddress:LOOP
#XXX FETCH Into的结果总是父级Cursor(cursor_bizId)的第一个bizId的查询结果!why?
FETCH cursor_matchedAddress INTO _rownum, _matchID, _matchedType, _matchedAddress, _x, _y;
IF done2 THEN
LEAVE loop_getMatchedAddress;
CLOSE cursor_matchedAddress;
END IF;
# 根据当前循环的rownum,更新指定候选匹配地址字段
# rownum=1时,更新4个匹配结果字段;rownumber=n时,更新字段<候选匹配地址n>
IF _rownum = 1 THEN
update 地名地址整合数据源表 set 匹配ID=_matchID,匹配精度=_matchedType,匹配地址=_matchedAddress,地址经度=_x,地址纬度=_y where 业务ID=bizId COLLATE utf8_unicode_ci;
ELSE
SET @matchedAddressField = CONCAT("候选匹配地址", _rownum - 1);
#MySQL5.7.8支持JSON序列化,暂用版本5.5,手动序列化
# SET @matchedAddress=JSON_ARRAY(匹配精度,匹配地址,地址经度,地址纬度,匹配ID);
SET @matchedAddress = CONCAT_WS(" | ", _matchedType, _matchedAddress,_x,_y, _matchID);
SET @sql = CONCAT("update 地名地址整合数据源表 SET ", @matchedAddressField, "='", @matchedAddress, "' where 业务ID='", bizId COLLATE utf8_unicode_ci,"'");
PREPARE stmt from @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP loop_getMatchedAddress;
END block_matchedAddress;
END LOOP loop_getBizId;
END
@geosmart
Copy link
Author

geosmart commented Mar 8, 2016

FETCH Into的结果总是父级Cursor(cursor_bizId)的第一个bizId的查询结果!why?
View的问题,换成temporary table,已解决,见gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment