T-SQL中的TRY CATCH块

时间:2011-02-14 14:36:39

标签: sql-server-2005 error-handling

我遇到了一个存储过程,它在更新尝试后立即出现以下错误处理块。以下是SP的最后几行。

这样做有什么好处吗?在我看来好像这个代码只是重新抛出它没有添加任何值时捕获的相同错误,并且如果Try Block完全被忽略,代码可能会表现为100%相同。

如果省略TRY块,生成的SP的行为会有什么不同吗?

BEGIN CATCH

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

END CATCH

4 个答案:

答案 0 :(得分:2)

我们通常在存储过程中执行的操作是像这样编写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 :(得分:2)

除非返回的任何消息部分出现“行错误”,否则将引用RAISERROR行而不是错误实际发生的行,这将没有区别。执行此操作的主要原因是@Chris说,允许您以编程方式使用/操作错误数据。

答案 2 :(得分:1)

如果您查看msdn page for RAISERROR,则可以看到此一般说明:

  

生成错误消息   启动错误处理   会话。 RAISERROR可以   引用用户定义的消息   存储在sys.messages目录中   动态查看或构建消息。   该消息作为服务器返回   呼叫错误消息   应用程序或相关的CATCH   TRY ... CATCH构造的块。

似乎“调用应用程序”将收到错误消息。可能是存储过程的创建者只想要报告错误消息,严重性和状态,而不能添加其他选项。这可能是出于安全问题或仅仅是调用应用程序不需要知道额外信息(可能是冗长或过于详细的信息)。

答案 3 :(得分:0)

存在细微差别,如下所示。

首先设置以下内容:

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

注意:pTMP2设置会影响XACT_ABORT的行为。

结论

使用TRY..CATCH的好处取决于您管理交易边界的方式。

  • 如果您回滚任何错误,则更改将被撤消。但这并不能消除附加处理等副作用。注意:如果其他会话同时使用TMP查询WITH(NOLOCK),则甚至可以观察到临时更改。
  • 但是,如果您不打算回滚某个事务,您可能会发现该技术对于防止某些数据更改的应用非常重要,而不是先前的错误。