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

如何修复PDO调用SQL Server存储过程报'@P1'附近语法错误

报错原因

报错根源是T-SQL存储过程的调用语法写错了:
SQL Server里调用存储过程时,不能用括号包裹参数列表——带括号传参是标量值函数的调用语法,不是存储过程的。你的代码里写EXEC sp_login(?, ?),PDO预处理阶段会把问号占位符替换成驱动自动生成的命名参数@P1、@P2,最终传给SQL Server的语句变成EXEC sp_login(@P1, @P2),数据库解析到这个不符合存储过程调用规则的写法,就会抛出@P1附近存在语法错误的提示。

另外你的现有代码还有两个明显的安全/逻辑问题:

  • 把用户提交的明文密码直接存在$_SESSION里,存在会话泄露后密码被盗的风险
  • 跳转头header发送后没有终止代码执行,存在逻辑被绕过的可能
修复方法
  1. 首先修正存储过程调用的SQL语句,两种合法写法选一个即可:
    • 按位置传参(最简单,直接去掉参数外的括号):
    $sql = "EXEC sp_login ?, ?";
    
    • 显式指定参数名(兼容性最好,推荐使用,注意参数名要和你存储过程定义的形参名完全一致):
    // 假设sp_login的两个形参分别是@utilizador、@password,按你实际定义调整
    $sql = "EXEC sp_login @utilizador = ?, @password = ?";
    
  2. 调整逻辑,不要把明文密码存入SESSION,header跳转后加exit终止执行,修正后的核心代码如下:
    session_start();
    // 直接从POST取参数做校验,不需要提前写入SESSION
    $utilizador = $_POST['utilizador'] ?? null;
    $password = $_POST['password'] ?? null;
    
    if (isset($utilizador) && isset($password)){    
        require 'ligacao_bd.php';
        $pdo = Conexao::getConnection();
        $sql = "EXEC sp_login @utilizador = ?, @password = ?"; 
        $statement = $pdo->prepare($sql);
        $statement->bindParam(1, $utilizador, PDO::PARAM_STR);
        $statement->bindParam(2, $password, PDO::PARAM_STR);
        $statement->execute();
        $resultado = $statement->fetch(PDO::FETCH_ASSOC);
    
        if ($resultado) {
            // 校验通过后仅把必要的用户标识存入SESSION即可,不要存明文密码
            $_SESSION["utilizador"] = $utilizador;
            header("location: utilizadores.php");
            exit; // 必须加终止语句,避免后续代码继续执行
        }else{
            echo "NO PERMISSIONS";
        }
    }
    

额外建议:不要在数据库里明文存储用户密码,存储过程里做校验时,应该用加盐哈希后的值做比对,避免数据拖库后所有用户密码泄露。


内容的提问来源于stack exchange,提问作者Antonio Jose

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:15:49