我正在制作一个存储过程以检查用户是否存在。问题是每当我向它传递正确的用户名时,它都会成功执行,但是当我传递错误的用户名时,它会进入无限循环。
我哪里错了?这是我的存储过程:
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
最佳答案
要修复您的代码,请对 done
变量使用条件测试来确定是否离开循环。 (done
变量初始化为 FALSE,然后在没有更多行时在 CONTINUE HANDLER 中设置为 TRUE。)
摆脱查询“count(*)
”查询,以及noRows
变量;不需要那些。 (在并发系统中,count(*) 查询返回的值可能与后面的查询返回的行数不同。(考虑到其他 session 可能会在您的过程运行时插入或删除行.)
同时删除对 @count
用户变量的引用。您混合了对用户 变量@count
和过程 变量count
的引用。这些是自变量。您的过程不需要使用 user 变量。相反,坚持使用在您的过程中声明的变量。 (保存用户变量以备不时之需。)
-- 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;
关于mysql - 存储过程进入死循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15450099/