如何在PHP中获取SQL Server存储过程的输出结果
解决SQL Server存储过程在PHP中获取多结果集与输出参数的问题
你的核心问题是没有正确遍历存储过程返回的所有结果集,同时当前SQL写法可优化,直接通过PHP绑定输出参数更高效,无需额外执行select语句。以下提供两种解决方案:
方案一:直接通过PHP绑定输出参数(推荐)
无需在SQL里声明变量和额外select,直接让PHP绑定存储过程的输出参数,跳过中间无关结果集后获取参数值,还能避免SQL注入风险。
调整后的SQL语句
EXEC dbo.Precio ?, ?, ?, ?, ?, ?, ?, ?
对应的PHP代码
// 定义输入输出参数初始值 $IDCliente = 123; // 替换为实际客户ID $NETO = null; $DTO1 = null; $DTO2 = null; $DTO3 = null; $CODIGO = null; $CODIGOEAN = null; $NOMBRE = null; // 参数数组:输入参数用SQLSRV_PARAM_IN,输出参数用SQLSRV_PARAM_OUT并指定类型 $params = [ [$IDCliente, SQLSRV_PARAM_IN], [$NETO, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT], [$DTO1, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT], [$DTO2, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT], [$DTO3, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT], [$CODIGO, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)], [$CODIGOEAN, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)], [$NOMBRE, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)] ]; // 准备并执行语句 $sql = "EXEC dbo.Precio ?, ?, ?, ?, ?, ?, ?, ?"; $stmt = sqlsrv_prepare($pc, $sql, $params); if ($stmt === false) die(print_r(sqlsrv_errors(), true)); if (sqlsrv_execute($stmt) === false) die(print_r(sqlsrv_errors(), true)); // 跳过存储过程返回的第一个结果集 while (sqlsrv_next_result($stmt)) {} // 输出参数已赋值,整理结果 $result = [ 'neto' => $NETO, 'DTO1' => $DTO1, 'DTO2' => $DTO2, 'DTO3' => $DTO3, 'CODIGO' => $CODIGO, 'CODIGOEAN' => $CODIGOEAN, 'NOMBRE' => $NOMBRE ]; echo json_encode($result);
方案二:正确遍历所有结果集(兼容原有SQL写法)
如果坚持保留原有SQL中的select语句,需修正遍历逻辑,确保捕获最后一个结果集:
修正后的PHP代码
$stmt = sqlsrv_prepare($pc, $sql); if ($stmt === false) die(print_r(sqlsrv_errors(), true)); sqlsrv_execute($stmt); $finalData = null; // 逐个遍历所有结果集,保留最后一个结果集的数据 do { if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $finalData = $row; } } while (sqlsrv_next_result($stmt)); echo json_encode($finalData);
原有代码失效原因
你原有的do-while循环中,每次先fetch再调用两次sqlsrv_next_result,会跳过部分结果集,无法正确捕获最后那个select生成的结果集。修正后的循环会逐一处理所有结果集,确保拿到目标数据。
内容的提问来源于stack exchange,提问作者Cesc Teruel Villanueva
相关产品推荐
相关产品推荐

