SQL SERVER:触发器出现异常时,如何退出

仓井NULL 2017-10-12 05:24:19
1.业务场景:数据库中有两个表:表A,表B
在表B上建立一个触发器:若在表B中插入数据,则在表A中也插入另外一个数据
现在需要模拟当触发器发生异常时:可以捕获异常,使表B仍可以正常插入记录,而表A不能
触发器:
CREATE trigger [deptinfo_add_ltsms]
on [his].[zd_bmks]
after insert
as

begin

begin try

insert his_itf.dbo.test--执行此语句一定会报错,用于模拟触发器错误,测试异常捕获
(USER_ID)
values
('9999999999999999')

end try

begin catch
if (@@error> 0)--异常捕获,但是没有作用,B表无数据
begin
rollback
return
end
end catch

end;

插入语句:(若屏蔽触发器,该语句可正常插入表B)
insert into [ihis].[zd_bmks]
(ksdm,ksmc,kslb,zxbz,yydm)
values
('29986','测试一科','81','0','30')
...全文
1947 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
仓井NULL 2017-10-13
  • 打赏
  • 举报
回复
引用 19 楼 z10843087 的回复:
不需要,他只是针对你这个触发器的。
嗯,我后来在微软官网也看到了,谢谢你啊,这个分我一级只能给100。。。所以,你就吃点亏吧
OwenZeng_DBA 2017-10-13
  • 打赏
  • 举报
回复
哈哈,开玩笑的。问题解决就行
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
不需要,他只是针对你这个触发器的。
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
引用 17 楼 z10843087 的回复:
或者你把你的语句发来看看
现在没有错了,但是,我们在触发器中:set xact_abort off,那么需不需要将再将他的状态置为on?
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
或者你把你的语句发来看看
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
引用 15 楼 qq_35800047 的回复:
最后这种哦,,不需要COMMIT了
是的,COMMIT换成了set xact_abort off,但是结果还是一样啊[/quote] 你就直接用我这个例子语句运行呢,我运行了,是正常的。
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
最后这种哦,,不需要COMMIT了[/quote] 是的,COMMIT换成了set xact_abort off,但是结果还是一样啊
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
引用 12 楼 qq_35800047 的回复:
还是那个问题啊,如果没有异常的话,还是会有错误
最后这种哦,,不需要COMMIT了
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
引用 11 楼 z10843087 的回复:
用这个吧,,2个都不会提示错误,如果有错误的时候要提示,你可以在print error 那里增加。。。
这问题有点费脑子啊,,至少要给200分哦


还是那个问题啊,如果没有异常的话,还是会有错误
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
还是那个问题啊,如果没有异常的话,还是会有错误
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
用这个吧,,2个都不会提示错误,如果有错误的时候要提示,你可以在print error 那里增加。。。 这问题有点费脑子啊,,至少要给200分哦
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
引用 9 楼 qq_35800047 的回复:
这样做。。还是会提示错误,但是数据都是插入成功的
所以如果可能的话,还是不要提示错误[/quote] ALTER TRIGGER [deptinfo_add_ltsms] ON t_b AFTER INSERT AS BEGIN set xact_abort off BEGIN TRY INSERT dbo.t_a ( id ) VALUES ( '2' ) PRINT @@trancount END TRY BEGIN CATCH PRINT 2 IF ( @@error > 0 )--异常捕获,但是没有作用,B表无数据 BEGIN PRINT 'ERROR' END END CATCH END;
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
这样做。。还是会提示错误,但是数据都是插入成功的[/quote] 所以如果可能的话,还是不要提示错误
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
引用 7 楼 z10843087 的回复:
[quote=引用 6 楼 qq_35800047 的回复:] 问题解决了记得结贴哦
额,异常的情况是可以这么处理,但是没有异常的情况下,就回报错了[/quote] ALTER TRIGGER [deptinfo_add_ltsms] ON t_b AFTER INSERT AS BEGIN COMMIT BEGIN TRY BEGIN TRAN INSERT dbo.t_a --执行此语句一定会报错,用于模拟触发器错误,测试异常捕获 ( id ) VALUES ( '99999999999' ) PRINT @@trancount COMMIT END TRY BEGIN CATCH IF ( @@error > 0 )--异常捕获,但是没有作用,B表无数据 BEGIN PRINT 5 ROLLBACK TRAN END END CATCH END; CREATE TABLE t_a ( id INT ) CREATE TABLE t_b ( id INT ) INSERT INTO t_b VALUES ( 1 ) 这样做。。还是会提示错误,但是数据都是插入成功的[/quote] 我这个其实要接入医院HIS,每天数据会上万次,如果报错,人家医院会不会有很大影响 以前会做ORACLE,这个SQL SERVER第一次做,如果ORACLE报错,那么医院的操作界面可能会有错误弹窗等异常状况,现在不知道SQL SERVER会不会有这种情况产生,也不敢这么直接去部署。。。。。。
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
引用 6 楼 qq_35800047 的回复:
问题解决了记得结贴哦
额,异常的情况是可以这么处理,但是没有异常的情况下,就回报错了[/quote] ALTER TRIGGER [deptinfo_add_ltsms] ON t_b AFTER INSERT AS BEGIN COMMIT BEGIN TRY BEGIN TRAN INSERT dbo.t_a --执行此语句一定会报错,用于模拟触发器错误,测试异常捕获 ( id ) VALUES ( '99999999999' ) PRINT @@trancount COMMIT END TRY BEGIN CATCH IF ( @@error > 0 )--异常捕获,但是没有作用,B表无数据 BEGIN PRINT 5 ROLLBACK TRAN END END CATCH END; CREATE TABLE t_a ( id INT ) CREATE TABLE t_b ( id INT ) INSERT INTO t_b VALUES ( 1 ) 这样做。。还是会提示错误,但是数据都是插入成功的
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
问题解决了记得结贴哦[/quote]

额,异常的情况是可以这么处理,但是没有异常的情况下,就回报错了
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
引用 3 楼 qq_35800047 的回复:
CREATE TABLE t_a (id int) CREATE TABLE t_b (id int) INSERT INTO t_b VALUES (1) SELECT * FROM t_b 虽然我觉得这并不是一个好主意,不过你可以在最开始就提交事务,解决上面的问题,还是会报错,不过A表会保存数据。
很有想法,亲测可用 我这样理解可以吗 开始的时候 在插入表B的时候,触发器启动,然后产生异常,触发器回滚,回滚的时间点为插入表B的时间节点到回滚的时间节点,造成表B和表A都是没有新的记录 修改后的触发器(加入COMMIT后) 插入及触发过程一样,由于触发器启动时就进行了一次提交,回滚的时间点为提交的时间节点到回滚的时间节点,造成表B中有记录(已经提交了)而表A没有新的记录生成(有产生了异常,而进行了回滚)[/quote] 问题解决了记得结贴哦
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
嗯,就是这个意思,
仓井NULL 2017-10-12
  • 打赏
  • 举报
回复
CREATE TABLE t_a (id int) CREATE TABLE t_b (id int) INSERT INTO t_b VALUES (1) SELECT * FROM t_b 虽然我觉得这并不是一个好主意,不过你可以在最开始就提交事务,解决上面的问题,还是会报错,不过A表会保存数据。[/quote] 很有想法,亲测可用 我这样理解可以吗 开始的时候 在插入表B的时候,触发器启动,然后产生异常,触发器回滚,回滚的时间点为插入表B的时间节点到回滚的时间节点,造成表B和表A都是没有新的记录 修改后的触发器(加入COMMIT后) 插入及触发过程一样,由于触发器启动时就进行了一次提交,回滚的时间点为提交的时间节点到回滚的时间节点,造成表B中有记录(已经提交了)而表A没有新的记录生成(有产生了异常,而进行了回滚)
OwenZeng_DBA 2017-10-12
  • 打赏
  • 举报
回复
ALTER trigger [deptinfo_add_ltsms] on t_b after insert as begin COMMIT begin try insert dbo.t_a --执行此语句一定会报错,用于模拟触发器错误,测试异常捕获 (id) values ('9999999999999999') end try begin catch if (@@error> 0)--异常捕获,但是没有作用,B表无数据 begin return end end catch end; CREATE TABLE t_a (id int) CREATE TABLE t_b (id int) INSERT INTO t_b VALUES (1) SELECT * FROM t_b 虽然我觉得这并不是一个好主意,不过你可以在最开始就提交事务,解决上面的问题,还是会报错,不过A表会保存数据。
加载更多回复(1)

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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