@@ ERROR и / или TRY - CATCH - PullRequest
       14

@@ ERROR и / или TRY - CATCH

15 голосов
/ 10 июля 2009

Будет ли Try-Catch регистрировать все ошибки, которые может @@ ERROR? В следующем фрагменте кода стоит проверить наличие @@ ERROR? Произойдет ли ВОЗВРАЩЕНИЕ 1111 когда-нибудь?

SET XACT_ABORT ON
BEGIN TRANSACTION

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

    SELECT @Error=@@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

Ответы [ 6 ]

14 голосов
/ 10 июля 2009

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

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

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

8 голосов
/ 10 июля 2009

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 была внутри, а не снаружи,

4 голосов
/ 10 июля 2009

Попробуй поймай, не все поймает

вот код, демонстрирующий, что

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

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

0 голосов
/ 11 июля 2009

Смысл «Try..Catch» в том, что вам не нужно проверять @@ ERROR для каждого оператора.

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

0 голосов
/ 10 июля 2009

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

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

0 голосов
/ 10 июля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...