Заголовок сообщения об исключении для внутреннего SQL Server - PullRequest
7 голосов
/ 04 декабря 2010

Следующий оператор SQL ниже является хорошим примером некоторого SQL, который выдает исключение с вложенными деталями. Кажется, что в части catch, я могу получить только внешние детали исключения Could not create constraint. See previous errors (не очень полезно!). Я хочу получить внутреннее сообщение об исключении:

Введение ограничения FOREIGN KEY «FK_TWO» в таблице «TABLE2» может вызвать циклы или несколько каскадных путей. Укажите НА УДАЛИТЬ НЕТ ДЕЙСТВИЙ или ВКЛ ОБНОВЛЕНИЕ НЕТ ДЕЙСТВИЙ, или изменить другое Ограничения FOREIGN KEY (вы можете получить это сообщение, запустив код без try-catch).

Как можно достичь этого в блоке Catch в T-SQL?

BEGIN TRY
      BEGIN TRAN;

        CREATE TABLE TABLE1 (USER_ID INTEGER NOT NULL PRIMARY KEY, USER_NAME
            CHAR(50) NOT NULL);

        CREATE TABLE TABLE2 (AUTHOR_ID INTEGER NOT NULL PRIMARY KEY, AUTHOR_NAME
            CHAR(50) NOT NULL, LASTMODIFIEDBY INTEGER NOT NULL, ADDEDBY INTEGER NOT
            NULL);

        ALTER TABLE TABLE2 ADD CONSTRAINT FK_ONE FOREIGN KEY (LASTMODIFIEDBY)
            REFERENCES TABLE1 (USER_ID) ON DELETE CASCADE ON UPDATE CASCADE;

        ALTER TABLE TABLE2 ADD CONSTRAINT FK_TWO FOREIGN KEY (ADDEDBY)
            REFERENCES TABLE1(USER_ID) ON DELETE NO ACTION ON UPDATE CASCADE;   

        COMMIT TRAN;
END TRY
BEGIN CATCH

      DECLARE @ERROR_MSG NVARCHAR(MAX), @SEVERITY INT, @STATE INT
      SELECT @SEVERITY = ERROR_SEVERITY(), @STATE = ERROR_STATE()
            , @ERROR_MSG = ERROR_MESSAGE() + ' err src line: ' + CAST( ERROR_LINE() AS NVARCHAR(20)) + ' ' + ISNULL(ERROR_PROCEDURE(), ''); 

      ROLLBACK;
      -- RE-THROW EXCEPTION FOR DIAGNOSTIC VISIBILITY
      RAISERROR (@ERROR_MSG ,@SEVERITY, @STATE); 
END CATCH;

[Изменить]

Так что после долгих поисков кажется, что нет решения этой проблемы. Надеюсь, они исправят это в следующей версии.

Ответы [ 2 ]

9 голосов
/ 04 декабря 2010

Вы не можете повторно выбросить исходную ошибку. Вы должны выдать ошибку new с номером ошибки выше 50000, которая содержит захваченное сообщение об ошибке. См. Обработка исключений и вложенные транзакции , например:

begin catch
    declare @error int, @message varchar(4000), @xstate int;
    select @error = ERROR_NUMBER()
        , @message = ERROR_MESSAGE();
raiserror ('Caught exception: %d: %s', 16, 1, @error, @message) ;
return;
end catch   

В статье, на которую я ссылаюсь, есть более подробный пример, охватывающий также обязательную проверку XACT_STATE() и смешивание блоков try / catch с семантикой транзакции.

В следующей версии («Denali») эта проблема исправлена, поскольку у вас есть возможность выдавать throw; без любого аргумента, который вызовет исходное исключение, как в других языках try / catch. См. TRY CATCH THROW: Ошибка обработки изменений в T-SQL

Обновлено

О, я как бы читаю пост по диагонали. Если возникло больше исключений, вы можете поймать только одно. Это все еще верно, с Денали тоже. Но в большинстве случаев возникают исключительные ситуации серьезности 0 (то есть они на самом деле являются отпечатками, а не исключениями), и они по-прежнему передаются клиенту в виде информационных сообщений (SqlConnection.InfoMessage события).

0 голосов
/ 07 декабря 2010

Сейчас нет решения этой проблемы.Согласно this , решение в следующей версии SQL Server будет заключаться в использовании нового ключевого слова throw, которое вызовет повторные ошибки.

...