1

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

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

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
4

2 回答 2

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;
于 2013-03-16T14:35:45.427 回答
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 专家

CREATE PROCEDURE `VerifyUserNPass`(userParam varchar(50), out result int)
BEGIN
 select COUNT(userName) into result from users where username = @userParam
END
于 2013-03-16T13:57:14.343 回答