日期:2014-05-17  浏览次数:21100 次

SQL server2005 触发器 异常处理 无法理解的现象
表 Temp1 {[value],[name]}

建立了一个触发器 TestTregger_on_Temp1_after_insert :


CREATE TRIGGER [dbo].[ti_on_Temp1_AFTINST]
   ON  [dbo].[Temp1]
AFTER INSERT
AS 
BEGIN
SET NOCOUNT ON;

--BEGIN TRY
--exec dbo.app_TestListenner 'Testing'
RAISERROR(N'Error testing',11,100)
        --END TRY BEGIN CATCH
--END CATCH
END


在尝试执行如下代码时,其结果令人不解:


BEGIN TRY
insert into Temp1([value],[name]) values ('ccc','BBBB')
if(@@error <> 0)
print 'Error occured'
else
print 'insert sucess'
END TRY BEGIN CATCH
print ERROR_MESSAGE() 
END CATCH


1.如果触发器中 没有 TRY - CATCH :(仅仅注释掉 TRY - CATCH ,其他语句顺序不变)
  A.insert 语句之外 也没有 TRY - CATCH,则有如下结果: (仅仅注释掉 TRY - CATCH ,其他语句顺序不变)
    "
     消息 50000,级别 16,状态 100,过程 ti_on_Temp1_AFTINST,第 17 行
     Error testing

     (1 行受影响)
     Error occured
    "

  有出错信息,但是insert 成功,表中有新数据(1 行受影响);

  B.如果insert 外层 有 TRY - CATCH,则结果变成:
    "
     Error testing
    "
    而且insert 不成功;

2.如果触发器中 有 TRY - CATCH :
   
    对应A的情况: insert 语句之外 没有 TRY - CATCH,则有如下结果:
    "
     消息 3616,级别 16,状态 1,第 3 行
     事务在触发器中结束。批处理已中止。
    "

    对应B的情况:insert 外层 有 TRY - CATCH,则结果变成:
    "
      事务在触发器中结束。批处理已中止。
    "
    
    但无论是A还是B,insert 语句都不会成功。

这是我在触发器中执行存储过程时遇到的现象。到底,TRY - CATCH 如何使用?为什么触发器中不用 TRY - CATCH 时,即使
出现异常仍能成功执行数据库的写操作而加上 TRY - CATCH 反而不行?更加奇怪的是触发器中不加 TRY - CATCH 时,insert 语句的结果还要依赖于执行insert 语句有没有被包在 TRY - CATCH 之中?这到底什么情况?



------最佳解决方案--------------------
应该是这样的:
1、A的情况:插入数据后,执行触发器,再触发器中产生一个错误,输出了Error testing,然后执行了print 'Error occured'
B的情况:插入数据后,再触发器中产生了一个错误,那么try捕获到错误后,执行了catch快,所以只有Error testing。但是因为事务发生了错误,所以插入的语句也被rollback可
------其他解决方案--------------------
我用触发器喜欢直接 调用rollback
你这样隐式的,如一楼所说,事务发生错误会回滚,但给我的感觉不安全
------其他解决方案--------------------
2、两种情况都是捕获到错误了,事务被取消了,然后就完了
------其他解决方案--------------------
引用:
应该是这样的:
1、A的情况:插入数据后,执行触发器,再触发器中产生一个错误,输出了Error testing,然后执行了print 'Error occured'
B的情况:插入数据后,再触发器中产生了一个错误,那么try捕获到错误后,执行了catch快,所以只有Error testing。但是因为事务发生了错误,所以插入的语句也被rollback可


看你的意思,在 1、A 情况下并非为一个完整的事务,所以有一半的提交成功而有一半失败?我试着在inert 语句之前加一个事务语句,情况