PHP не может получить [код результата] и [выходной параметр], назначенные в блоке BEGIN CATCH ... END CATCH хранимой процедуры SQL Server 2016 - PullRequest
0 голосов
/ 01 января 2019

У меня есть простая таблица и сохраненный процесс, подобный следующему:

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

Сохраненный процесс может вернуть код ошибки, а также ERROR_MESSAGE (), который я назначаю в блоке CATCH.

Результат |ErrorMsg

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-сервера.

1 Ответ

0 голосов
/ 02 января 2019

У меня были похожие проблемы, и я предлагаю следующее:

  • всегда ставьте 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 работает.Надеюсь, это поможет.

...