PHP读取MySQL存储过程第二个结果集绑定变量报错求助
解决PHP调用MySQL存储过程读取第二个结果集时bind_result报错的问题
碰到这种情况我太熟悉了!问题出在你切换结果集后,直接调用mysqli_stmt_bind_result时,语句句柄还保留着第一个结果集的元数据,导致绑定的变量数和第二个结果集的字段数不匹配。咱们来一步步解决这个问题:
核心原因
当你执行mysqli_stmt_next_result($call)切换到第二个结果集后,原来的语句句柄并没有自动更新结果集的字段信息。这时候再用mysqli_stmt_bind_result,它还是按照第一个结果集的9个字段来匹配,而第二个结果集只有3个字段,自然就报“变量数不匹配”的错了。
推荐解决方案:用mysqli_stmt_get_result处理多结果集
相比直接绑定结果,mysqli_stmt_get_result会返回一个标准的结果集对象,能清晰处理每个结果集,代码也更易维护。修改后的代码如下:
public function GetSession($sessionId) { $conn = mysqli_connect(DbConstants::$servername, DbConstants::$username, DbConstants::$password, DbConstants::$dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $call = mysqli_prepare($conn, 'CALL Sp_Session_GetById(?)'); mysqli_stmt_bind_param($call, 'i', $sessionId); mysqli_stmt_execute($call); // 处理第一个结果集:获取Session基础数据 $sessionResult = mysqli_stmt_get_result($call); $sessionRow = mysqli_fetch_assoc($sessionResult); $session = new Session( $sessionRow['id'], $sessionRow['startTime'], $sessionRow['duration'], $sessionRow['description'], $sessionRow['instructor_id'], $sessionRow['aircraft_id'], $sessionRow['display'], $sessionRow['bookable'], $sessionRow['cancelled'], [] ); // 处理第二个结果集:获取关联的sessiontype数据 if(mysqli_stmt_more_results($call)) { mysqli_stmt_next_result($call); $sessionTypeResult = mysqli_stmt_get_result($call); $sessionTypes = []; // 循环读取所有行 while ($row = mysqli_fetch_assoc($sessionTypeResult)) { $sessionTypes[] = [ 'sessiontype_id' => $row['sessiontype_id'], 'spaces' => $row['spaces'], 'enabled' => $row['enabled'] ]; } // 将数据赋值给Session对象(假设类中有对应的属性) $session->sessionTypes = $sessionTypes; } // 清理资源 mysqli_free_result($sessionResult); if(isset($sessionTypeResult)) mysqli_free_result($sessionTypeResult); mysqli_stmt_close($call); mysqli_close($conn); return $session; }
注意事项
- 这个方法需要你的PHP环境安装了
mysqlnd驱动(大部分现代PHP环境默认都有),如果没有的话,你需要先启用它。 - 别忘了在最后清理结果集和数据库连接,避免资源泄漏。
备选方案(无mysqlnd时)
如果实在无法使用mysqlnd,你需要在切换结果集后重新存储结果、获取字段数,再动态绑定变量。这种方式比较繁琐,示例如下(只展示关键部分):
// 切换到第二个结果集后 mysqli_stmt_store_result($call); $fieldCount = mysqli_stmt_num_fields($call); // 动态创建绑定变量 $vars = []; for ($i = 0; $i < $fieldCount; $i++) { $vars[] = &${"var_$i"}; } call_user_func_array('mysqli_stmt_bind_result', array_merge([$call], $vars)); // 然后循环读取 $sessionTypes = []; while(mysqli_stmt_fetch($call)) { $sessionTypes[] = [ 'sessiontype_id' => $var_0, 'spaces' => $var_1, 'enabled' => $var_2 ]; }
不过还是强烈推荐用第一种方法,代码更简洁不易出错。
内容的提问来源于stack exchange,提问作者webdevduck
相关产品推荐
相关产品推荐

