@@ERROR и/или TRY - CATCH

Будет ли Try-Catch фиксировать все ошибки, которые могут возникнуть при @@ERROR? В следующем фрагменте кода стоит проверить на @@ERROR? Возникнет ли RETURN 1111?

SET XACT_ABORT ON
BEGIN TRANSACTION

BEGIN TRY
    --do sql command here  <<<<<<<<<<<

    SELECT @[email protected]@ERROR
    IF @Error!=0
    BEGIN
        IF XACT_STATE()!=0
        BEGIN
            ROLLBACK TRANSACTION
        END
        RETURN 1111
    END

END TRY
BEGIN CATCH

    IF XACT_STATE()!=0
    BEGIN
        ROLLBACK TRANSACTION
    END
    RETURN 2222

END CATCH

IF XACT_STATE()=1
BEGIN
    COMMIT
END

RETURN 0

Ответ 1

Следующая статья является обязательной для прочтения Erland Sommarskog, SQL Server MVP: реализация обработки ошибок с помощью хранимых процедур

Также обратите внимание, что ваш блок TRY может не работать, и ваш блок CATCH может быть обойден

Еще одна вещь: хранимые процедуры, использующие обработку ошибок старого стиля и точки сохранения, могут работать не так, как предполагалось, когда они используются вместе с блоками TRY… CATCH. Избегайте смешивания старых и новых стилей обработки ошибок.

Ответ 2

TRY/CATCH ловушки больше. Это невероятно и удивительно лучше.

DECLARE @foo int

SET @foo = 'bob' --batch aborting pre-SQL 2005
SELECT @@ERROR
GO
SELECT @@ERROR  --detects 245. But not much use, really if the batch was a stored proc
GO


DECLARE @foo int
BEGIN TRY
    SET @foo = 'bob'
    SELECT @@ERROR
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE(), ERROR_NUMBER()
END CATCH
GO

Использование TRY/CATCH в триггерах также работает. Сброс триггера также используется для прерывания партии: больше нет, если TRY/CATCH также используется в триггере.

Ваш пример был бы лучше, если BEGIN/ROLLBACK/COMMIT находится внутри, а не снаружи, конструкцию

Ответ 3

Try Catch не будет ловить все

вот какой код, чтобы продемонстрировать, что

    BEGIN TRY
      BEGIN TRANSACTION TranA
     DECLARE  @cond INT;
     SET @cond =  'A';
    END TRY
    BEGIN CATCH
     PRINT 'a'
    END CATCH;
    COMMIT TRAN TranA

Сервер: Msg 3930, уровень 16, состояние 1, строка 9 Текущая транзакция не может быть зафиксирована и не может поддерживать операции, которые записываются в файл журнала. Отмените транзакцию. Сервер: Msg 3998, уровень 16, состояние 1, строка 1 Неопределенная транзакция обнаружена в конце пакета. Сделка отменяется.

Ответ 4

Я не верю, что управление когда-либо достигнет инструкции RETURN - как только вы попадете в блок TRY, любая ошибка будет передана в блок CATCH. Тем не менее, есть некоторые очень серьезные ошибки, которые могут привести к остановке партии или даже самого соединения (Erland Sommarskog написал на тему ошибок в SQL Server здесь и здесь - к сожалению, он не обновил их, включив TRY... CATCH). Я не уверен, что вы можете использовать такую ​​ошибку, но тогда @@ERROR тоже не годится.

Ответ 5

По моему опыту, в соответствии с книгой Online, TRY... Блоки CATCH будут захватывать все события, которые будут генерировать ошибки (и, таким образом, установить @@ERROR на ненулевое значение). Я не могу придумать никаких обстоятельств, когда это не применимо. Таким образом, нет, возвращаемое значение никогда не будет установлено в 1111, и не стоит включать эту ошибку @@Error.

Однако обработка ошибок может быть очень важна, и я буду хеджировать свои ставки для таких ситуаций, как DTC, связанные серверы, службы уведомлений или брокерских услуг и другие функции SQL, с которыми у меня было очень мало опыта. Если вы можете, проверьте свои более странные ситуации, чтобы увидеть, что на самом деле произойдет.

Ответ 6

Весь смысл "Try..Catch" заключается в том, что вам не нужно проверять наличие @@ERROR для каждого утверждения.

Так что это не стоит.