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

Laravel 10调用SQL Server存储过程如何获取输出参数

解决Laravel 10调用SQL Server存储过程获取输出参数的问题

问题核心

你的代码无法获取存储过程的输出参数,主要原因是没有正确声明输出参数的类型,且存在SQL拼接错误、重复执行查询的问题。以下是修正方案:

错误点分析

  1. 错误使用Db::select():这个方法会直接执行SQL并返回结果,后续再用PDO prepare属于重复操作,破坏了参数绑定逻辑。
  2. 输出参数未标记OUTPUT:存储过程中@pSuccessFlag和@pMessage是输出参数,但SQL调用里没有明确声明OUTPUT关键字,SQL Server不会返回这些参数的值。
  3. 参数拼接不规范:直接拼接null或字符串会导致语法错误,且存在SQL注入风险,应该用PDO参数绑定。

修正后的完整代码

public function login(Request $request)
{
    $conn = DB::connection('sqlsrv');
    $pdo = $conn->getPdo();

    // 构造存储过程调用SQL,明确标记输出参数为OUTPUT
    $sql = <<<SQL
SET NOCOUNT ON;
EXEC sp_Login 
    @pSuccessFlag = ?,
    @pMessage = ?,
    @pCallingPage = ?,
    @pOperation = ?,
    @pid = ?,
    @puname = ?,
    @ppassword = ?,
    @premark = ?,
    @POpwd = ?,
    @PROLE_ID = ?,
    @PIS_ACTIVE = ?,
    @POTP = ?,
    @POTP_DATE = ?,
    @PFACILITY_ID = ?,
    @PCREATED_BY = ?,
    @PCREATED_ON = ?,
    @PMODIFIED_BY = ?,
    @PMODIFIED_ON = ?,
    @PUSER_TYPE_ID = ?,
    @PEMP_ID = ?,
    @PSERVER_LOGTIME = ?;
SQL;

    $stmt = $pdo->prepare($sql);

    // 绑定输出参数:指定参数类型为输出,设置长度匹配存储过程定义
    $successFlag = null;
    $message = null;
    $stmt->bindParam(1, $successFlag, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 2);
    $stmt->bindParam(2, $message, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 2000);

    // 绑定输入参数(测试用硬编码值)
    $stmt->bindValue(3, 'Login');
    $stmt->bindValue(4, 'GetAll_for_login');
    $stmt->bindValue(5, null);
    $stmt->bindValue(6, 'admin');
    $stmt->bindValue(7, '55e01f2a13f587e1e9e4aedb8242d');
    $stmt->bindValue(8, null);
    $stmt->bindValue(9, null);
    $stmt->bindValue(10, null);
    $stmt->bindValue(11, null);
    $stmt->bindValue(12, null);
    $stmt->bindValue(13, null);
    $stmt->bindValue(14, null);
    $stmt->bindValue(15, null);
    $stmt->bindValue(16, null);
    $stmt->bindValue(17, null);
    $stmt->bindValue(18, null);
    $stmt->bindValue(19, null);
    $stmt->bindValue(20, null);
    $stmt->bindValue(21, null);

    $stmt->execute();

    // 处理多个结果集
    $res = [];
    do {
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $res[] = $rows;
    } while ($stmt->nextRowset());

    // 执行完成后,输出参数会被赋值
    return $this->sendResponse('Done', [
        'maindata' => $res,
        'param1' => $successFlag,
        'param2' => $message
    ]);
}

关键说明

  1. SET NOCOUNT ON:必须保留,否则SQL Server会返回额外的计数结果,干扰结果集的遍历。
  2. bindParam输出参数绑定:
    • 第三个参数PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT标记该参数为输入输出类型
    • 第四个参数是参数的最大长度,必须和存储过程中定义的VARCHAR(2)、VARCHAR(2000)匹配
  3. 参数绑定顺序:必须和SQL中的?占位符顺序严格对应
  4. 结果集遍历:通过nextRowset()切换到下一个结果集,确保获取所有返回的数据

之前报错写法的问题修复

你之前的报错写法存在语法错误(@POTP_DATE后面少了=),且同样没有正确绑定输出参数。用上面的参数绑定方式可以彻底避免这类语法问题,同时防止SQL注入。

内容的提问来源于stack exchange,提问作者Vaibhav K. Patil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:14:59