原始答案(用我常用的方法来获取可能的输出参数的返回值和存储过程的返回值):
您可以考虑以下几点:
- 存储过程的返回值是一个整数,因此您需要使用适当的绑定。
- 如果是
OUTPUT 参数,您需要在PDOStatement::bindParam 调用中设置maxLength 参数。正如文档中所解释的,要...指示参数是来自存储过程的 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 语句中的错误。
- 不检查
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