You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:51:20