Mysql 存储过程转到无限循环
我制作一个存储过程是为了检查用户是否存在。问题是,每当我传递正确的用户名时,它都会成功执行,但当我传递错误的用户名时,它会经历一个无限循环 我哪里做错了?以下是我的存储过程:Mysql 存储过程转到无限循环,mysql,Mysql,我制作一个存储过程是为了检查用户是否存在。问题是,每当我传递正确的用户名时,它都会成功执行,但当我传递错误的用户名时,它会经历一个无限循环 我哪里做错了?以下是我的存储过程: CREATE PROCEDURE `VerifyUserNPass`(userParam varchar(50), out result int) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE tempUser varchar(50) default '';
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
确保为所有分支增加循环计数器,而不仅仅是在succes分支中,并使用result变量保存结果
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;
我希望这将返回相同的结果(但我不是
确保为所有分支增加循环计数器,而不仅仅是在succes分支中,并使用result变量保存结果
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;
我希望这将返回相同的结果(但我不是
要修复代码,请对
done
变量使用条件测试来确定是否退出循环。(当不再有行时,done
变量初始化为FALSE,然后在CONTINUE处理程序中设置为TRUE。)
去掉查询“count(*)
”查询和noRows
变量;这些是不需要的。(在并发系统中,count(*)查询返回的值可能与稍后查询返回的行数不同。(请考虑在您的过程运行时,其他会话可能插入或删除行。)
另外,还要去掉对
@count
用户变量的引用。用户变量@coount
和过程变量count
的引用是混合的。这些都是独立变量。过程不需要使用用户变量。相反,请坚持使用中声明的变量您的过程。(保存用户变量以备需要时使用。)
一种更有效的编码方法是,通过在查询中添加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;
要修复代码,请对
done
变量使用条件测试来确定是否离开循环。(当不再有行时,done
变量初始化为FALSE,然后在CONTINUE处理程序中设置为TRUE。)
去掉查询“count(*)
”和noRows
变量;这些都是不需要的。(在并发系统中,count(*)查询可能返回一个不同于后续查询返回的行数的值。(请考虑在您的过程运行时,其他会话可以插入或删除行。)
另外,还要去掉对
@count
用户变量的引用。用户变量@coount
和过程变量count
的引用是混合的。这些都是独立变量。过程不需要使用用户变量。相反,请坚持使用中声明的变量您的过程。(保存用户变量以备需要时使用。)
一种更有效的编码方法是,通过在查询中添加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;
我认为COUNT变量返回的结果是1=true(存在)和0=false(不存在)?是的。我只回答了这个问题,但它肯定有更多的问题:-)嘿,也许你是对的?我只是猜测,因为代码块的格式不正确。我认为COUNT变量返回的结果是1=true(存在)和0=false(不存在)?是的。我只回答了这个问题,但它肯定有更多的问题:-)嘿,也许你是对的?我只是猜测,因为代码块的格式不好。你对用户变量的引用混合在一起(
@count
)和过程变量count
。不需要noRows
变量,也不需要对其进行任何测试。使用done
变量来确定是否已处理所有行,而不是运行单独的查询来获取行数。在查询中包含WHERE子句以仅返回ro将更有效ws,其中用户名与userParam的值匹配。您混合引用了用户变量(@count
)和过程变量count
。不需要noRows
变量,也不需要对其进行任何测试。使用done
变量来确定是否已处理所有行,而不是运行单独的查询来获取行数。在查询中包含WHERE子句以仅返回ro将更有效ws,其中用户名与userParam的值匹配。