TRY CATCH Block в T-SQL - PullRequest
       16

TRY CATCH Block в T-SQL

7 голосов
/ 14 февраля 2011

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

Есть ли польза от этого? Мне кажется, что этот код просто выводит ту же ошибку, что и без каких-либо добавленных значений, и что код, вероятно, будет вести себя на 100% так же, если бы Try Block был полностью опущен.

Было бы ЛЮБОЕ различие в поведении результирующего SP, если бы блок TRY был опущен?

BEGIN CATCH

SELECT @ErrMsg = ERROR_MESSAGE(), @ErrSev = ERROR_SEVERITY(), @ErrState = ERROR_STATE()
        RAISERROR (@ErrMsg, @ErrSev, @ErrState)

END CATCH

Ответы [ 4 ]

2 голосов
/ 14 февраля 2011

Если исключить тот факт, что часть "ошибка строки произошла" в любом возвращаемом сообщении будет ссылаться на строку RAISERROR, а не на строку, на которой фактически произошла ошибка, разницы не будет.Как говорит @Chris, основная причина сделать это - программно использовать / манипулировать данными об ошибках.

2 голосов
/ 14 февраля 2011

То, что мы обычно делаем в нашей хранимой процедуре, это напишем блок catch следующим образом:

BEGIN CATCH
  DECLARE @i_intErrorNo int          
  DECLARE @i_strErrorMsg nvarchar(1000)          
  DECLARE @i_strErrorProc nvarchar(1000)          
  DECLARE @i_intErrorLine int          

  SELECT @i_intErrorNo=Error_Number()          
  SELECT @i_strErrorMsg=Error_Message()          
  SELECT @i_strErrorProc=Error_Procedure()          
  SELECT @i_intErrorLine=Error_Line()   

  INSERT INTO error table ////// Insert statement. 

END CATCH 

Это то, что мы используем для хранения ошибки.Для правильного сообщения пользователю я всегда использую выходной параметр хранимой процедуры, чтобы показать подробную / требуемую причину ошибки.

1 голос
/ 14 февраля 2011

если вы посмотрите на страницу msdn для RAISERROR , то увидите это общее описание:

Создает сообщение об ошибке и инициирует обработку ошибки для сеанса.RAISERROR может ссылаться на пользовательское сообщение, хранящееся в представлении каталога sys.messages, или создавать сообщение динамически.Сообщение возвращается как сообщение об ошибке сервера вызывающему приложению или соответствующему блоку CATCH конструкции TRY… CATCH.

Похоже, что «вызывающее приложение» получит сообщение об ошибке.Может случиться так, что создатель хранимой процедуры хотел сообщить только сообщение об ошибке, серьезность и состояние, а также не добавлять другие параметры.Это может быть из-за проблем безопасности или просто из-за того, что вызывающему приложению не нужно было знать дополнительную информацию (возможно, она была многословной или слишком подробной).

0 голосов
/ 22 мая 2015

Существует небольшая разница, как показано ниже.

Сначала настройте следующее:

CREATE TABLE TMP
( ROW_ID int NOT NULL,
  ALTER TABLE TMP ADD CONSTRAINT PK_TMP PRIMARY KEY CLUSTERED (ROW_ID)
)
GO
CREATE PROC pTMP1
AS
BEGIN TRY
  INSERT INTO TMP VALUES(1)
  INSERT INTO TMP VALUES(1)
  INSERT INTO TMP VALUES(2)
END TRY
BEGIN CATCH
  DECLARE @ErrMsg varchar(max)= ERROR_MESSAGE(),
          @ErrSev int = ERROR_SEVERITY(),
          @ErrState int = ERROR_STATE()
        RAISERROR (@ErrMsg, @ErrSev, @ErrState)
END CATCH
GO
CREATE PROC pTMP2
AS
  INSERT INTO TMP VALUES(1)
  INSERT INTO TMP VALUES(1)
  INSERT INTO TMP VALUES(2)
GO

Теперь выполните следующее:

SET NOCOUNT ON
DELETE TMP
exec pTMP1
SELECT * FROM TMP
DELETE TMP
exec pTMP2
SELECT * FROM TMP
SET NOCOUNT OFF
--Cleanup
DROP PROCEDURE pTMP1
DROP PROCEDURE pTMP2
DROP TABLE TMP

Вы должны получитьследующие результаты:

Msg 50000, Level 14, State 1, Procedure pTMP1, Line 12
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
ROW_ID
-----------
1

Msg 2627, Level 14, State 1, Procedure pTMP2, Line 4
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
The statement has been terminated.
ROW_ID
-----------
1
2

Обратите внимание, что версия TRY..CATCH не выполнила третий оператор INSERT, в то время как процедура pTMP2 выполнила.Это связано с тем, что управление переходит к CATCH, как только возникает ошибка.

ПРИМЕЧАНИЕ. Параметр XACT_ABORT влияет на поведение pTMP2.

Заключение

Преимущество использования TRY..CATCH, как продемонстрировано, зависит от того, как вы управляете границами транзакции.

  • Если вы откатываетесь по любой ошибке, изменения будут отменены.Но это не устраняет побочные эффекты, такие как дополнительная обработка.ПРИМЕЧАНИЕ. Если другой сеанс одновременно запрашивает TMP с использованием WITH(NOLOCK), он может даже наблюдать временное изменение.
  • Однако, если вы не собираетесь откатывать транзакцию, вы можете найти методочень важно предотвратить применение определенных изменений данных, несмотря на более раннюю ошибку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...