加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 带有游标的存储过程以奇怪的方式执行

发布时间:2020-12-13 22:46:22 所属栏目:PHP教程 来源:网络整理
导读:我有一个存储过程,它应该使用游标处理表中的行.该过程大部分时间都有效,但有时它不会完全执行.我知道这是因为我有一个简单的调试工具,嵌入到代码中,它将特定的行和变量记录到专用的调试表中.最有趣的是,从 PHP运行时总会出现问题.如果我使用mysql客户端我从
我有一个存储过程,它应该使用游标处理表中的行.该过程大部分时间都有效,但有时它不会完全执行.我知道这是因为我有一个简单的调试工具,嵌入到代码中,它将特定的行和变量记录到专用的调试表中.最有趣的是,从 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;

是整个程序的全球性.

因此,它可能很好地捕获其他未找到的事件,而不是来自光标提取,并导致循环提前退出.

尝试在游标提取周围使用开始结束块,并在那里声明一个处理程序.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读