2009-07-10 71 views
14

会尝试捕获捕获该@@ ERROR可以所有的错误?在下面的代码片段中,是否值得检查@@ ERROR?返回1111会不会发生?@@ ERROR和/或TRY - CATCH

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 

回答

12

下面的文章是一个必须由厄兰Sommarskog,SQL服务器MVP阅读:Implementing Error Handling with Stored Procedures

还要注意的是Your TRY block may fail, and your CATCH block may be bypassed

一件事:使用旧式的错误处理和保存点可能无法正常工作作为存储过程当它们与TRY ... CATCH块一起使用时有意。 Avoid mixing old and new styles of error handling.

+0

同意+ 1 – SQLMenace 2009-07-10 19:36:52

+3

Erland Sommarskog的链接文章适用于SQL Server 2000。对于他的SQL Server上的文章2005年在这里看到:http://www.sommarskog.se/error_handling_2005.html – 2014-11-25 19:17:46

+0

@ RichardMarskell-Drackir有一个用于SQL Server 2008?我的意思是说,链接2005及更高版本,但.. – Apostrofix 2015-03-31 13:00:25

8

的try/catch陷阱多。它非常好,非常好。

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

我不相信控制永远不会到达RETURN statement--一旦你在try块是,所产生的任何错误都会将控制权交给CATCH块。不过,也有一些非常严重的错误,可能会导致该批次甚至连接本身中止(厄兰Sommarskog写了错误的话题在SQL Server herehere - 不幸的是,他并没有更新他们包括试试。 ..抓住)。我不确定你是否可以捕捉那些错误,但是,@@ ERROR也不好。

+3

不,你不能用一个严重错误赶上高于20。而且,你不能赶上警告。 – NYSystemsAnalyst 2009-07-10 19:35:07

0

这是我的经验在于,根据联机丛书,的try ... catch块将捕获会产生错误的所有事件(和,因此,设置@@ ERROR为非零值)。我可以想到在任何情况下这都不适用。所以不,返回值永远不会被设置为1111,并且包含@@错误检查是不值得的。

但是,错误处理可能非常关键,并且我会针对诸如DTC,链接服务器,通知或经纪服务等其他SQL特性以及我几乎没有经验的其他SQL特性对付我的投注。如果可以的话,测试你更奇怪的情况,看看会发生什么。

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号线 当前事务无法提交,不能支持写入日志文件的操作。回滚事务。 服务器:消息3998,级别16,状态1,行1 在批处理结束时检测到不可提交的事务。事务回滚。

0

“在try..catch”整点是,这样你就不必检查@@ ERROR的每一个发言。

所以这是不值得的。