2015-07-07 2 views
1

Сегодня я пытался написать транзакцию в хранимой процедуре, которая в некоторых возвращает разные числа. Коду C# необходимо знать, что именно было ошибкой. Проблема заключается в том, что если транзакция не завершена, она вызывает одно и то же исключение.Исключение T-SQL Throw в транзакции

Я не мог исключить исключение внутри транзакции, всегда давал неправильный синтаксис. Я пытался с этим рисунком:

THROW 51000, 'The record does not exist.', 1; 

Можно ли сделать что-то вроде этого:

BEGIN TRAN 
    TRY 

    IF... 
    THROW ERROR 4; 

    IF.. 
    THROW ERROR 2; 

COMPLETE TRAN; 
CATCH 
    RETURN ERROR NUMBER; 

Я просто нужно определенное число ошибки возвращается из хранимой процедуры.

Не могли бы вы привести мне пример?

P.S. Я забыл, какая версия нашего сервера sql, нет, я не в офисе. Это либо 2008 или 2012.

+0

[Использование кода возврата] (https://technet.microsoft.com/en-us/library/ms190778 (v = sql.105) .aspx) –

+0

[КАК: Возвращение ошибок и предупреждений от хранимой процедуры SQL Server в ADO.NET] (https://support.microsoft.com/en-us/kb/321903) –

+0

Почему бы вам просто не использовать код возврата? Зачем бросать только, чтобы скрыть исключение? –

ответ

2

Вы можете использовать следующий синтаксис:

BEGIN TRY 
    BEGIN TRANSACTION 
      IF ... RAISERROR(51001, 16, 1) 
      IF ... RAISERROR(51002, 16, 1) 
    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    DECLARE @ErrorNumber INT = ERROR_NUMBER(); 
    DECLARE @ErrorLine INT = ERROR_LINE(); 
    DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(); 
    DECLARE @ErrorSeverity INT = ERROR_SEVERITY(); 
    DECLARE @ErrorState INT = ERROR_STATE(); 

    IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION; 

    RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState); 
END CATCH 

Номер ошибки должен быть больше 50000. Вы можете добавить их с помощью процедуры sp_addmessage. Throw была представлена ​​в Sql Server 2012. Есть некоторые отличия. Вы можете легко найти их в MSDN.

1

Вы должны использовать RAISERROR (подробнее в documentation) вместо THROW (см. documentation).

THROW будет только повторно выбрасывать существующее исключение внутри блока CATCH, вместо этого вызывая полное новое исключение. Он был введен в SQL Server 2012. Основное использование двух функций, которые вызывают ошибку, довольно просто. Если ошибка произошла внутри TRY, и вы повторно выбросите ошибку в своем блоке CATCH с использованием RAISERROR - как это было в современном уровне техники в 2008 году - оно может предоставить много полезной информации, но кодовая линия, в которой произошла ошибка, сдвигается на где вы подняли ошибку, используя RAISERROR, а не в строке, где действительно произошла ошибка. Используя THROW, он будет повторно отображать ошибку со всей информацией, даже с исходной строкой, в которой первоначально произошла ошибка.

Вместо этого вы можете бросить свое собственное исключение с помощью этого:

RAISERROR(N'Your Errormessage',16,1) 

Кстати, каждое сообщение об ошибке используется RAISERROR будет иметь ErrorMessage 50000 или выше. Вы можете определить свои собственные сообщения об ошибках с их собственным идентификатором (выше 50000). Если вы определили свой собственный идентификатор сообщения, вы можете использовать RAISERROR бросать определенную пользовательскую ошибку, как это:

RAISERROR(50001,16,1) 

Side информацию: Вы можете перегрузить RAISERROR для анализа значений в сообщение об ошибке.

RAISERROR(N'A error occurred while iterating over row ID %i',16,1,@rowId) 
Смежные вопросы