SQL server2005 触发器 异常处理 无法理解的现象

rularys 2012-10-22 10:59:04
表 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 之中?这到底什么情况?


...全文
253 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
2、两种情况都是捕获到错误了,事务被取消了,然后就完了
  • 打赏
  • 举报
回复
应该是这样的:
1、A的情况:插入数据后,执行触发器,再触发器中产生一个错误,输出了Error testing,然后执行了print 'Error occured'
B的情况:插入数据后,再触发器中产生了一个错误,那么try捕获到错误后,执行了catch快,所以只有Error testing。但是因为事务发生了错误,所以插入的语句也被rollback可
rularys 2012-10-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

我用触发器喜欢直接 调用rollback
你这样隐式的,如一楼所说,事务发生错误会回滚,但给我的感觉不安全
[/Quote]

我在触发器之中引发异常只是模拟存储过程出现异常的情况,不是为了隐式地让事务回滚。相反,我是想即使调用存储过程出现了异常,也要能搞提交insert 操作。问题是即使使用了 TRY-CATCH ,事务依然回滚了——不使用反而出乎意料得达到效果,但是这样的结果是不明确的,所以也不能用
DBA_磊仔 2012-10-22
  • 打赏
  • 举报
回复
我用触发器喜欢直接 调用rollback
你这样隐式的,如一楼所说,事务发生错误会回滚,但给我的感觉不安全
rularys 2012-10-22
  • 打赏
  • 举报
回复
或者是我对 SQL 中的 TRY-CATCH 理解有问题?
rularys 2012-10-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

应该是这样的:
1、A的情况:插入数据后,执行触发器,再触发器中产生一个错误,输出了Error testing,然后执行了print 'Error occured'
B的情况:插入数据后,再触发器中产生了一个错误,那么try捕获到错误后,执行了catch快,所以只有Error testing。但是因为事务发生了错误,所以插入的语句也被rollback可
[/Quote]

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

这里我本意是在触发器中条用从存储过程,这些存储过程只是事件监听,所以它们的成功与否、是否有异常都不能影响insert 语句的执行,所以触发器中调用事件监听过程时加了TRY - CATCH 。可没想到的是,不加 TRY- CATCH ,监听的存储过程即使有异常,insert 语句该成功还是成功,除非insert 语句本身包含在 TRY-CATCH 快之内;而触发器之中如果加了 TRY-CATCH ,那么只要监听存储过程有异常,也会影响到insert 语句的结果——TRY - CATCH 反而成了摆设。

22,300

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧