php – 带有游标的存储过程以奇怪的方式执行
我有一个存储过程,它应该使用游标处理表中的行.该过程大部分时间都有效,但有时它不会完全执行.我知道这是因为我有一个简单的调试工具,嵌入到代码中,它将特定的行和变量记录到专用的调试表中.最有趣的是,从
PHP运行时总会出现问题.如果我使用mysql客户端我从来没有遇到过这个问题.
程序(以稍微缩短的方式呈现)如下: CREATE PROCEDURE findnextedge(IN lastid BIGINT) findnext_context:BEGIN DECLARE stop BOOLEAN DEFAULT FALSE; DECLARE count INT DEFAULT 0; DECLARE cur_fid BIGINT DEFAULT 0; DECLARE cur_pid1 BIGINT DEFAULT 0; DECLARE cur_pid2 BIGINT DEFAULT 0; DECLARE cur CURSOR FOR SELECT fid,pid1,pid2 FROM edges WHERE pid1 = lastid; DECLARE CONTINUE HANDLER FOR NOT FOUND SET stop = TRUE; CALL debuglog(0,'findnextedge','lastid',lastid,NULL,NULL); SELECT SQL_CALC_FOUND_ROWS fid FROM edges WHERE pid1 = lastid; SET count = FOUND_ROWS(); CALL debuglog(1,'count',count,NULL); IF count = 0 THEN DELETE FROM paths WHERE pid1 = lastid AND pid2 = 0; SELECT COUNT(*) INTO count FROM paths WHERE pid2 = 0; CALL debuglog(2,NULL); IF count = 0 THEN SET @count = 1; END IF; LEAVE findnext_context; END IF; DELETE FROM paths WHERE pid1 = lastid AND pid2 = 0 ORDER BY pid1 LIMIT 1; OPEN cur; CALL debuglog(6,'open',TRUE,NULL); REPEAT FETCH cur INTO cur_fid,cur_pid1,cur_pid2; CALL debuglog(7,'stop',stop,NULL); IF stop = FALSE THEN CALL debuglog(3,'cur_fid',cur_fid,'cur_pid1','cur_pid2',cur_pid2); // DO MAIN JOB // ... CALL debuglog(5,NULL); END IF; CALL debuglog(8,NULL); UNTIL stop = TRUE END REPEAT; CLOSE cur; END; 如果出现问题,则产生整个输出: point context name1 value1 name2 value2 name3 value3 counter time 0 findnext lastid 0 NULL NULL NULL NULL 0 2012-11-27 18:29:56 1 findnext count 1 NULL NULL NULL NULL 1 2012-11-27 18:29:56 6 findnext open 1 NULL NULL NULL NULL 2 2012-11-27 18:29:56 7 findnext stop 0 NULL NULL NULL NULL 3 2012-11-27 18:29:56 根据日志,在点7中,刚刚取出光标停止值为假,但执行既没有到达点3也没有到达8. 看起来发生了一些内部错误,但我不确定如何捕获它.奇怪的是,这种情况会发生在相同的数据上,并且会不时发生. 附: MySQL版本5.0.51b,PHP 5.2.6. P.S.S.我已经设法找到一个相关的问题 – Calling a Stored Procedure Within a Cursor Loop,Without Tripping the Continue Handler.正如我的过程的名称所暗示的那样,它从外部过程中的循环内部调用(顺便说一下,它通过“路径”表循环,另一个继续处理程序),所以它类似于那些情况,并且可能在某种程度上很重要.我已经尝试了链接问题的解决方案,但它也没有帮助. 找到了解决方案,答案如下. 解决方法
停止循环的处理程序,如:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET stop = TRUE; 是整个程序的全球性. 因此,它可能很好地捕获其他未找到的事件,而不是来自光标提取,并导致循环提前退出. 尝试在游标提取周围使用开始结束块,并在那里声明一个处理程序. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |