存储过程进入无限循环

时间:2013-03-16 13:54:16

标签: mysql

我正在制作存储过程以检查用户是否存在。问题是每当我传递正确的用户名时,它就会成功执行但是当我传递错误的用户名时,它会经历一个无限循环。

我哪里错了?这是我的存储过程:

CREATE PROCEDURE `VerifyUserNPass`(userParam varchar(50), out result int)
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE tempUser varchar(50) default '';
    DECLARE count int default 0;
    DECLARE noRows int;

    DECLARE userList cursor for select userName from users;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    select count(*) into noRows from users;

    OPEN userList;
    read_loop: LOOP
        FETCH userList into tempUser;
        IF tempUser = userParam THEN
                SET @count = count + 1;
                LEAVE read_loop;
        ELSEIF count > noRows THEN
                LEAVE read_loop;
        END IF;

    END LOOP;
    CLOSE userList;

    select count into result;

END

2 个答案:

答案 0 :(得分:1)

要修复代码,请对done变量使用条件测试来确定是否退出循环。 (done变量初始化为FALSE,然后在没有更多行的情况下在CONTINUE HANDLER中设置为TRUE。)

删除查询“count(*)”查询和noRows变量;那些是不需要的。 (在并发系统中,count(*)查询可能返回一个与以后查询返回的行数不同的值。(考虑到其他会话在程序运行时插入或删除行的可能性) 。)

还要删除对@count用户变量的引用。对于用户变量@coount过程变量count,您有多种引用。这些是自变量。您的过程无需使用用户变量。相反,坚持使用在您的过程中声明的变量。 (在需要时保存用户变量。)

-- select count(*) into noRows from users;
read_loop: LOOP
    FETCH userList into tempUser;
    IF done THEN
       LEAVE read_loop;
    END IF;
    IF tempUser = userParam THEN
        SET count = 1;
        LEAVE read_loop;
    END IF;
END LOOP;

一种更有效的代码编写方法是让数据库通过在查询中添加WHERE子句来查找您感兴趣的行。 (您无需获取与您感兴趣的条件不匹配的行。)

修改游标定义以包含谓词(即WHERE子句中的条件)以限制返回的行:

DECLARE userList cursor for select userName from users
  WHERE userName = userParam LIMIT 1;

我不明白这里需要一个程序。本机SQL语句会更有效,例如。

SELECT 1 AS found FROM users u WHERE u.userName = 'foo' LIMIT 1;

答案 1 :(得分:0)

确保不仅在succes分支中增加所有分支的循环计数器,并使用结果变量来保存结果。

DECLARE userFound int default 0;
......
read_loop: LOOP
    FETCH userList into tempUser;
    SET @count = @count + 1;
    IF tempUser = userParam THEN
           SET @userFound = 1
           LEAVE read_loop;
    ELSEIF count > noRows THEN
            LEAVE read_loop;
    END IF;
    .....
    select userFound into result;

我希望这会返回相同的结果(但我不是MySql expert

CREATE PROCEDURE `VerifyUserNPass`(userParam varchar(50), out result int)
BEGIN
 select COUNT(userName) into result from users where username = @userParam
END