PHP调用SQL预存语句报错:缺少@DeliverySurcharge参数
解决SQL Server存储过程调用参数缺失的错误
你遇到的问题很明确:调用存储过程时没有在SQL语句中声明足够的参数占位符,导致SQL Server认为你漏传了@DeliverySurcharge参数。下面一步步帮你修复:
错误原因分析
原存储过程需要6个参数(3个输入、3个输出),但你的PHP代码里写的SQL调用语句:
$sql = "{call my_prepared_statement( ?, ?, ? )}";
只写了3个占位符,对应3个输入参数,完全没给后面3个输出参数留位置。SQL Server自然会判定你没传@DeliverySurcharge这个输出参数,抛出错误。
修复步骤
1. 修正SQL调用语句
把占位符数量补全,对应6个参数:
$sql = "{call my_prepared_statement( ?, ?, ?, ?, ?, ? )}";
这里的6个?依次对应:@CustNum(IN)、@PostCode(IN)、@Suburb(IN)、@DeliveryCode(OUT)、@DeliverySurcharge(OUT)、@ErrMsg(OUT),和你定义的$params数组顺序完全匹配。
2. 优化输出参数的类型定义
为了避免类型不匹配或者结果截断,建议给输出参数明确指定SQL类型和长度,比如:
$params = array( array($custNum, SQLSRV_PARAM_IN), array($postcode, SQLSRV_PARAM_IN), array($suburbname, SQLSRV_PARAM_IN), // 对应@DeliveryCode nvarchar(15) output array(&$dcode, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_NVARCHAR(15)), // 对应@DeliverySurcharge float output array(&$dsur, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT, SQLSRV_SQLTYPE_FLOAT), // 对应@ErrMsg varchar output,这里假设长度是255,你可以根据存储过程实际定义调整 array(&$emsg, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR(255)) );
3. 确保获取输出参数的值
有些存储过程执行后,需要调用sqlsrv_next_result来移动到结果集的末尾,才能正确获取输出参数的值。所以在执行查询后加上这一步:
if( $stmt3 === false ) { echo "<br/>Error in executing statement 3.<br/>"; die( print_r( sqlsrv_errors(), true)); } // 移动到结果集末尾,确保输出参数被赋值 sqlsrv_next_result($stmt3); echo "surcharge: " . $dsur . " --- code: " . $dcode . " --- error message: " . $emsg;
完整修复后的代码
$serverName = "XX"; $connectionInfo = array( "Database"=>"XX", "UID"=>"XX", "PWD"=>"XX"); $conn = sqlsrv_connect( $serverName, $connectionInfo); if($conn) { echo "Connection established"; // 修正:补全6个参数占位符 $sql = "{call my_prepared_statement( ?, ?, ?, ?, ?, ? )}"; $custNum = "XX"; $postcode = "2222"; $suburbname = "XX"; $dcode = ""; // 初始化空字符串,避免未定义问题 $dsur = 0.0; $emsg = ""; // 优化参数类型定义 $params = array( array($custNum, SQLSRV_PARAM_IN), array($postcode, SQLSRV_PARAM_IN), array($suburbname, SQLSRV_PARAM_IN), array(&$dcode, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_NVARCHAR(15)), array(&$dsur, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_FLOAT, SQLSRV_SQLTYPE_FLOAT), array(&$emsg, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR(255)) ); $stmt3 = sqlsrv_query( $conn, $sql, $params); if( $stmt3 === false ) { echo "<br/>Error in executing statement 3.<br/>"; die( print_r( sqlsrv_errors(), true)); } // 确保获取输出参数 sqlsrv_next_result($stmt3); echo "<br/>surcharge: " . $dsur . " --- code: " . $dcode . " --- error message: " . $emsg; } else { echo "Connection could not be established"; }
这样修改后,应该就能正常调用存储过程并获取输出参数的值了。如果还有问题,可以检查存储过程的参数顺序、类型是否和你的代码完全匹配哦~
内容的提问来源于stack exchange,提问作者rosyTown
相关产品推荐
相关产品推荐

