我有一个简单的表和一个存储的过程,如下所示:
CREATE TABLE dbo.Test
(
TestTime DATETIME
)
INSERT INTO dbo.Test (TestTime)
VALUES('2018-12-21T13:25:45')
CREATE PROCEDURE dbo.TestProc
@pErrorMsg NVARCHAR(512) OUTPUT
AS
BEGIN
DECLARE @result INTEGER
SET @result = 0
SET @pErrorMsg = N'OK';
BEGIN TRY
UPDATE dbo.Test
SET TestTime = '2018-12-21T13:25:45a' -- wrong time value to raise error!
WHERE TestTime = '2018-12-21T13:25:45'
END TRY
BEGIN CATCH
SET @pErrorMsg = ERROR_MESSAGE()
SET @result = 1
END CATCH
RETURN @result
END
--Test the proc, and it seems to work fine:
BEGIN
DECLARE @res INTEGER
SET @res = 0
DECLARE @errMsg NVARCHAR(128)
EXEC @res = dbo.TestProc @errMsg OUTPUT
SELECT @res AS Result, @errMsg AS ErrorMsg
END
存储的过程可以返回错误代码以及我在 CATCH 块中分配的 ERROR_MESSAGE()。
结果 | 错误消息
1 | 从字符串转换日期和/或时间时转换失败。
我的 php 代码:
$sql = "{? = call dbo.TestProc(?)}";
$res = 123;
$errorMsg = utf8_encode("abcd1234");
$paramRes = array(&$res, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_INT);
$paramErrorMsg = array(&$errorMsg, SQLSRV_PARAM_OUT);
$params = array($paramRes, $paramErrorMsg);
$affectedRows = 0;
$conn = sqlsrv_connect(<your_server>, <your_credential>);
$stmt = sqlsrv_query($conn, $sql, $params);
$affectedRows = sqlsrv_rows_affected($stmt); // this works well
$nxtRes = sqlsrv_next_result($stmt); // This asks the sql driver to update the result code and output parameter variables
echo "</br>result code=" . strval($res) . ", error msg=" . $errorMsg . "</br>"
问题是,如果我修改存储的过程以便它可以成功更新数据,我的 php 代码可以捕获返回代码 (0) 和错误消息 ("OK"),但如果我只保留存储的过程如上所述,我的 php 代码无法捕获这些内容。
之前遇到过相同问题的人可以给我一些提示吗?谢谢。我使用 php7 和 MS PHP 驱动程序 5.2 用于 SQL 服务器。
我有类似的问题,我建议如下:
- 始终将
SET NOCOUNT ON
放在存储过程的开头。 - 从
sqlsrv_query()
获取所有结果集。INSERT
,UPDATE
或DELETE
语句也返回受影响的行数作为结果集(当SET NOCOUNT
OFF
时),而不仅仅是SELECT
语句。
我通常以这种方式获取结果:
<?php
...
do {
# Fetch data, if it's a SELECT statement
#while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
#}
$affected = sqlsrv_rows_affected($stmt);
} while (sqlsrv_next_result($stmt));
...
?>
我已经复制了您的测试用例并SET NOCOUNT ON
工作。我希望这有所帮助。