Вопрос по sql-server, tsql, sql-server-2005 – @@ ERROR и / или TRY - CATCH

14

Будет ли Try-Catch регистрировать все ошибки, которые может @@ ERROR? В следующем фрагменте кода стоит проверить наличие @@ ERROR? Произойдет ли возврат 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

Ваш Ответ

6   ответов
0

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

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

0

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

Нет, вы не можете перехватить ошибку с серьезностью выше 20. Также вы не можете перехватить предупреждения.
13

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

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

Еще одна вещь: хранимые процедуры, использующие обработку ошибок старого стиля и точки сохранения, могут не работать должным образом, если они используются вместе с TRY & # x2026; ЗАХВАТЫВАЮТ БЛОКИ.Избегайте смешивания старых и новых стилей обработки ошибок.

@ RichardMarskell-Drackir есть ли для SQL Server 2008? Я имею в виду ссылку говорит 2005 и позже, но ..
Договорились +1 на это
@Apostrofix - Изменения с 2005+ должны быть относительно минимальными по сравнению с изменениями, внесенными в период с 2000 по 2005 год, поэтому я полагаю, что статья 2005 года по-прежнему применима.
Связанная статья Эрланда Соммарскога предназначена для SQL Server 2000. Его статью о SQL Server 2005 смотрите здесь:sommarskog.se/error_handling_2005.html
5

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

    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 В конце пакета обнаруживается незафиксированная транзакция. Сделка откатывается.

Я тоже его использую, но не вижу, как вы демонстрируете, когда коммит находится вне try / catch
Верно, но коммит внутри переместится в блок catch и никогда не запустится. И вы также ожидаете отката в блоке catch. Кроме того, OP имеет значение SET XACT_ABORT ON, которое имеет автоматический откат.
Я понимаю, что просто пытался подчеркнуть, что catch не может поймать все ... Я всегда использую SET XACT_ABORT ON в своих процессах
тот же результат, вам нужно проверить XACT_STATE, чтобы быть уверенным из-за все еще не перехватываемых ошибок и обреченного состояния
почему бы не начать / зафиксировать внутри попытки?
8

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

0

что вам не нужно проверять @@ ERROR для каждого утверждения.

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

Вы имеете в виду проверку на@@ERROR внутриTRY...CATCH не стоит. Ваше первоначальное утверждение не было ясным.

Похожие вопросы