MySQL存储过程OUT值获取失败:PDO调用出现fetch()错误求助
问题分析与解决方案
核心问题梳理
你遇到的错误Call to a member function fetch() on bool本质是第二个query()执行失败返回了false,根源出在存储过程语法错误、参数赋值错误,以及PHP处理存储过程的方式不当这三个方面。
1. 修正存储过程的语法与参数问题
你的存储过程存在两处关键错误:
IF EXISTS语句缺少闭合括号,导致语法报错;- 错误使用会话变量
@returnValue而非定义的OUT参数returnValue,导致返回值无法正确传递。
修正后的存储过程代码:
DELIMITER $$ CREATE DEFINER=`lvcs_ukpi`@`localhost` PROCEDURE `Login`(IN `param_login` VARCHAR(30), IN `param_senha` VARCHAR(30), OUT `returnValue` INT) NO SQL BEGIN -- 修正IF EXISTS的闭合括号,统一字段名(注意原代码混用了password和senha,这里以senha为准) IF EXISTS(SELECT * FROM Users WHERE LOWER(login) = LOWER(param_login) AND senha = param_senha) THEN SELECT * FROM Users WHERE login = param_login AND senha = param_senha; SET returnValue = 0; -- 直接使用定义的OUT参数,而非会话变量@returnValue ELSE SET returnValue = -999; END IF; END$$ DELIMITER ;
2. 修正PHP代码的错误处理逻辑
原PHP代码存在SQL注入风险,且未正确处理存储过程的多结果集,导致连接状态异常。以下是安全且正确的实现:
// 使用PDO预处理语句避免SQL注入 $stmt = $conn->prepare("CALL Login(:login, :senha, @returnValue)"); $stmt->bindParam(':login', $login, PDO::PARAM_STR); $stmt->bindParam(':senha', $senha, PDO::PARAM_STR); // 执行存储过程 $stmt->execute(); // 读取登录成功时返回的用户信息 $userInfo = null; if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $userInfo = $row; } // 必须消耗所有剩余结果集,否则连接会处于锁定状态 while ($stmt->nextRowset()) { // 无需处理,仅用于清空结果集队列 } // 获取OUT参数的返回值 $stmt = $conn->prepare("SELECT @returnValue AS returnValue"); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); $valor = $result['returnValue']; // 后续业务逻辑 if ($valor === 0) { echo "登录成功!用户信息:" . print_r($userInfo, true); } else { echo "登录失败,错误码:" . $valor; }
错误原因详解
- 存储过程语法错误:
IF EXISTS(...)的条件括号未闭合,导致存储过程执行失败,PHP调用时第一个query()返回false,后续连接状态异常,第二个query()也返回false,最终调用fetch()时触发错误。 - 参数赋值错误:存储过程中用
@returnValue(会话变量)代替了定义的OUT参数returnValue,导致返回值无法正确传递到外部。 - 未处理多结果集:存储过程执行时会先返回用户信息的结果集,若不消耗这个结果集就直接执行后续查询,PDO连接会处于未就绪状态,导致后续查询失败。
内容的提问来源于stack exchange,提问作者Libania Paes
相关产品推荐
相关产品推荐

