如何获取存储过程的返回值? PHP | PDO

问题描述 投票:0回答:2

我想显示SQL Server SP的返回值。我尝试过使用这种方式,但没有成功。

我正在使用 PHP PDO 进行数据库连接,并且正在执行 SQL Server 存储过程。

$feesObj = new FeesConfig('config/fees.ini');
$feesConfig = $feesObj->getFeesConfig();
                                
$studentId = $user->getSyStudentId();
$statement = $conn->prepare('exec ?= usp_GetStudentDegreeLevel ?');
$statement->bindParam(1, $retval, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT);
$statement->bindParam(2, $studentId, PDO::PARAM_INT);
$statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);

var_dump("return value". $retval);exit;

此 SP 执行的输出

NULL

预期结果

1

这段代码我哪里错了。我正在致电 SQL Server SP。

php sql-server pdo
2个回答
0
投票

原始答案(使用我通常的方法来获取可能的输出参数的返回值和存储过程的返回值):

您可以考虑以下事项:

  • 存储过程的返回值是一个整数,因此您需要使用适当的绑定。
  • 如果有
    OUTPUT
    参数,您需要在
    maxLength
    调用中设置
    PDOStatement::bindParam
    参数。正如文档中所述,要 ...指示参数是存储过程中的 OUT 参数,您必须显式设置长度
  • 您需要获取所有可能的结果集(使用
    PDOStatement::nextRowset
    )才能获取输出参数的值。或者,作为一个选项,如果存在
    INSERT
    UPDATE
    语句,请将
    SET NOCOUNT ON
    作为存储过程中的第一行。正如文档中所述,此语句 ... 停止显示受 Transact-SQL 语句或存储过程影响的行数的消息作为结果集的一部分返回

下面是使用 SQL Server 2017、PHP 7.4.8 和 PHP Driver for SQL Server 5.8 的简化示例:

存储过程:

CREATE PROCEDURE usp_GetStudentDegreeLevel 
    @StudentId INT  
AS  
BEGIN
    SELECT 'Information about the student' AS StudentInfo;
    RETURN 1;
END

PHP代码:

<?php
$server   = 'server\instance,port';
$database = 'database';
$username = 'username';
$password = 'password';
try {
    $conn = new PDO("sqlsrv:server=$server;Database=$database", $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
} catch( PDOException $e ) {
    die( "Error connecting to SQL Server".$e->getMessage());
}

try { 
    // 
    $sql = "EXEC ? = usp_GetStudentDegreeLevel ?";
    $statement = $conn->prepare($sql);
    if ($statement === false) {
        echo print_r($conn->errorInfo(), true);
        exit;
    }
    // Execution
    $retval    = 0;
    $studentId = 1;
    $statement->bindParam(1, $retval, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
    $statement->bindParam(2, $studentId, PDO::PARAM_INT);
    if ($statement->execute() === false) {
        echo print_r($conn->errorInfo(), true);
        exit;
    }   
    // Fetch data. 
    do {
       if ($statement->columnCount() > 0) {
           while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
              echo print_r($row, true); 
           };
        };  
    } while ($statement->nextRowset());
    //
    var_dump("Return value: " . $retval); 
    $statement = null;
} catch (PDOException $e) {
    echo $e->getMessage();
    exit;   
}

$conn = null;
?>

结果:

Array ( [StudentInfo] => Information about the student ) string(15) "Return value: 1"

更新(一个示例,重现意外的返回值):

我重现此错误的唯一方法是组合:

  • 使用
    PDO::ERRMODE_SILENT
    作为默认错误处理模式。
  • 存储过程中的错误和/或 SQL 语句中的错误。
  • No 检查
    PDO::prepare
    和/或
    PDOStatement::execute
    调用的结果是否成功。

PHP代码:

// PDO object with default error handling (PDO::ERRMODE_SILENT, but for PHP version before 8.0.0)
$conn = new PDO("sqlsrv:server=$server;Database=$database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);

// SQL statement with error
$sql = "EXEC ? = usp_GetStudentDegreeLevel ,?";
$statement = $conn->prepare($sql);
$statement->bindParam(1, $retval,  PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 1);
$statement->bindParam(2, $studentId, PDO::PARAM_INT);
$statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);

//
var_dump($retval); 

结果:

NULL

0
投票

@Zhorov - 感谢您的回答 - 它派上了用场。 RETURN 值似乎在第二个行集中。

如果使用 fetchAll,则需要后接 nextrowset 才能获取 RETURN 值。

$statement->execute();
$row = $statement->fetchAll(PDO::FETCH_ASSOC);
$statement->nextRowset()
var_dump($retval);
© www.soinside.com 2019 - 2024. All rights reserved.