如何摆脱“错误1329:没有数据 - 提取,选择或处理零行”

时间:2010-08-11 22:15:00

标签: sql mysql stored-procedures

我有一个存储过程,不需要返回任何值。它运行顺畅,没有任何问题。但是,它在完成运行后输出错误消息:

  

错误:无数据 - 提取,选择或处理零行

如何摆脱此错误消息?

CREATE PROCEDURE `testing_proc`()  
    READS SQL DATA  
BEGIN  
    DECLARE done INT DEFAULT 0;
    DECLARE l_name VARCHAR(20);
    DECLARE my_cur CURSOR FOR
        SELECT name FROM customer_tbl;
    OPEN my_cur;
        my_cur_loop:
        LOOP FETCH my_cur INTO l_name;
            IF done = 1 THEN
                LEAVE my_cur_loop;
            END IF;
            INSERT INTO names_tbl VALUES(l_name);
        END LOOP my_cur_loop;
    CLOSE my_cur;
END

7 个答案:

答案 0 :(得分:38)

我猜您只是忘了在帖子中包含以下内容:

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

您的代码是正确的,但是mysql的错误/奇怪行为会导致警告出现,即使它已被处理。如果在程序结束时添加“虚拟”语句来调用表并且成功,则可以避免这种情况,这将清除警告。 (见http://dev.mysql.com/doc/refman/5.5/en/show-warnings.html) 在你的情况下:

SELECT name INTO l_name FROM customer_tbl LIMIT 1;

循环结束后。 在MySQL 5.5.13上,警告在Linux和Windows上消失。 我评论了MySQL Bug 60840,我希望他们将来会修复它......

答案 1 :(得分:26)

您需要定义一个继续处理程序,如:

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

所以它看起来像:

DECLARE done INT DEFAULT 0;
DECLARE l_name VARCHAR(20);
DECLARE my_cur CURSOR FOR
    SELECT name FROM customer_tbl;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN my_cur;
    my_cur_loop:
    LOOP FETCH my_cur INTO l_name;
        IF done = 1 THEN
            LEAVE my_cur_loop;
        END IF;
        INSERT INTO names_tbl VALUES(l_name);
    END LOOP my_cur_loop;
CLOSE my_cur;

答案 2 :(得分:8)

我遇到了这个并拉了我的头发,直到我在official mysql docs

中遇到了这个
  

在MySQL 5.6.3之前,如果语句产生警告或错误   导致调用条件处理程序,处理程序可能无法清除   诊断区域。这可能会导致外观   处理程序未被调用。以下讨论演示了   问题并提供解决方法。

单击链接并滚动到底部以获取详细信息,但修复是包括成功选择INSIDE CONTINUE HANDLER:

  DECLARE CONTINUE HANDLER FOR NOT FOUND
    BEGIN
       SELECT 1 INTO @handler_invoked FROM (SELECT 1) AS t;
    END;

答案 3 :(得分:3)

我在这里尝试了解决方案,没有,包括继续处理程序为我工作。我仍然在MySQL错误日志中收到消息。我发现这也是我的“选择...进入...”这是有道理的,但我真的认为继续处理程序适用于游标。无论哪种方式,我发现使用“found_rows()”来查明返回的行是否完美。这意味着简单的“select into”语句必须转换为游标,但它没有多少工作并且确实解决了问题。

DECLARE v_rowcount      integer unsigned;
DECLARE cur_entries cursor for
        select app_name, proc_name, error_code, sum(occurrences) occurrences
        from that_table...; 
open cur_entries; 
set v_rowcount = found_rows();
if v_rowcount > 0 then
  fetch cur_entries into v_app_name, v_proc_name, v_error_code, v_occurrences;
  ...
end if;
close cur_entries;

我在我的个人博客上写了这个:http://tinky2jed.wordpress.com/technical-stuff/mysql/mysql-no-data-zero-rows-fetched-how-to-code-for-it/

答案 4 :(得分:1)

我不知道这是否修复了游标问题,但是我使用存储的函数遇到了这个警告,发现如果你使用:

RETURN (SELECT x From myTable...);

而不是

SELECT x into myVar...return myVar

我从这个有用的文档得到了这个: http://bugs.mysql.com/bug.php?id=42834

答案 5 :(得分:1)

通常在超出游标范围时会发生这种情况,因此请检查FETCH语句所在的循环条件

答案 6 :(得分:0)

我在代码中遇到了同样的错误,我意识到我没有增加我的循环变量(使用while循环),因此循环将变为无限。

在您的代码中,您也没有将“ done”设置为1,因此我认为代码显示错误。

在下面的代码中,我添加了变量“ count”,而不是变量“ done”,该变量用表中的记录数初始化,并在每次插入后减小。当count = 0时,循环终止:

CREATE PROCEDURE `testing_proc`()  
READS SQL DATA  
BEGIN
  DECLARE count INT;
  DECLARE l_name VARCHAR(20);

  SELECT count(*) into count from customer_tbl;

  DECLARE my_cur CURSOR FOR
    SELECT name FROM customer_tbl;

  OPEN my_cur;
    my_cur_loop:
    LOOP FETCH my_cur INTO l_name;
    INSERT INTO names_tbl VALUES(l_name);
    SET count = count - 1;

    IF count = 0 THEN
            LEAVE my_cur_loop;
    END IF;

    END LOOP my_cur_loop;
  CLOSE my_cur;
END

我希望这会有所帮助!