原文:在论坛中出现的比较难的sql问题:20(触发器专题2)


最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。

本篇是触发器专题,有很多触发器的问题。

1、关于触发器中回滚的问题。

在官方文档http://technet.microsoft.com/zh-cn/library/ms181299.aspx中“互操作性”段落中有这么一句:

    触发器继续执行 ROLLBACK 语句之后的所有其余语句。 如果这些语句中的任意语句修改数据,则不回滚这些修改。 执行其余的语句不会激发嵌套触发器。

其中“执行其余的语句不会激发嵌套触发器”,是否意味着在回滚操作后面的语句如果继续执行的话,后面语句触发的触发器就不会执行了。比如后面的语句有针对一个表的update操作,而这张表又有update的触发器,这个时候update会执行成功,但触发器不会执行?

但是很奇怪,我做了一个实验,发现,即使是嵌套触发器,也能够被触发,和微软文档上说的不一样。

从下面的insert时的输出,可以看出,在触发器中rollback之后的语句,是可以执行的,另外,update另一个表的操作也执行成功,并且触发了触发器。


  1. --drop table t1
  2. --drop table t2
  3. create table t1(id int)
  4. create table t2(id int)
  5. insert into t2
  6. values(100)
  7. go
  8. create trigger dbo.trigger_t1
  9. on t1
  10. for insert
  11. as
  12. rollback;
  13. select '这是rollback之后的语句,这里能执行'
  14. update t2
  15. set id = 1;
  16. go
  17. create trigger dbo.trigger_t2
  18. on t2
  19. for update
  20. as
  21. select '这是t2的update触发器,这里能执行'
  22. go
  23. --插入数据
  24. insert into t1
  25. values(1)
  26. /*
  27. 这是rollback之后的语句,这里能执行
  28. 这是t2的update触发器,这里能执行
  29. 消息 3609,级别 16,状态 1,第 3 行
  30. 事务在触发器中结束。批处理已中止。
  31. */
  32. --没有记录
  33. select * from t1
  34. select * from t2
  35. /*
  36. id
  37. 1
  38. */

2、触发器的错误处理

http://bbs.csdn.net/topics/390637035

我在A表写了个触发器 插入后执行,是向B表插入一条记录


  1. USE [test]
  2. GO
  3. SET ANSI_NULLS ON
  4. GO
  5. SET QUOTED_IDENTIFIER ON
  6. GO
  7. ALTER TRIGGER [dbo].[tba_delete]
  8. ON [dbo].[tba]
  9. AFTER INSERT
  10. AS
  11. BEGIN
  12. SET NOCOUNT ON;
  13. insert into test.dbo.tbb(title,info) values('title','info');
  14. END

在A表插入数据后正常。当我把 语言改为:

insert into test.dbo.tbb(id,title,info) values(1,'title','info');

故意出错。问题出现了,当触发器内的语句出错,向A表插入的数据就不能成功插入。

向朋友们求教个问题。我要如何把触发器中的出错信息记录下来?或者在什么地方可以查看到触发器执行时是否出错了,及查看错误的信息?

我的解法:


  1. USE [test]
  2. GO
  3. SET ANSI_NULLS ON
  4. GO
  5. SET QUOTED_IDENTIFIER ON
  6. GO
  7. create table [tba](title varchar(20),info varchar(20))
  8. create table tbb(title varchar(20),info varchar(20))
  9. --创建一个存放错误信息的表
  10. create table tb_error_message
  11. (
  12. obj_name nvarchar(30),
  13. obj_type nvarchar(15),
  14. err_msg nvarchar(100),
  15. err_date datetime
  16. )
  17. go
  18. drop trigger tba_delete
  19. go
  20. create TRIGGER [dbo].[tba_delete]
  21. ON [dbo].[tba]
  22. AFTER INSERT
  23. AS
  24. BEGIN
  25. SET NOCOUNT ON;
  26. begin try
  27. --这里模拟插入title列的数据长度,超过了定义时的20
  28. insert into test.dbo.tbb(title,info) values('title1111111111111111111','info');
  29. end try
  30. begin catch
  31. --错误了就回滚
  32. rollback;
  33. insert into tb_error_message
  34. values('tba_delete','trigger',error_message(),getdate())
  35. end catch
  36. END
  37. go
  38. insert into tba
  39. values('11','11')
  40. /*
  41. 消息 3930,级别 16,状态 1,过程 tba_delete,第 16 行
  42. 当前事务无法提交,而且无法支持写入日志文件的操作。请回滚该事务。
  43. 语句已终止。
  44. */
  45. --查询出错的信息
  46. select *
  47. from tb_error_message
  48. /*
  49. obj_name obj_type err_msg err_date
  50. tba_delete trigger 将截断字符串或二进制数据。 2013-11-08 12:32:16.750
  51. */

3、忽略触发器中的错误

http://bbs.csdn.net/topics/390623172

我的情况是这样的: 当向A表插入数据时,需要向某用户发送信息通知,由于插入数据方是第三方软件做的,我控件不了,所以我在A表加个触发器来实现,现在问题是发送信息这里的错误是可以忽略的,就是说假如发送失败不影响数据的插入,请问我在触发器里如何忽略错误,让事务继续执行.

我的思路是:


  1. --先保存一个事务点
  2. SAVEPOINT xxx
  3. begin try
  4. --或者是调用存储过程,或者就直接写代码
  5. exec 发送信息的存储过程
  6. end try
  7. begin catch
  8. select '执行失败'
  9. --一旦出错,只是回滚到上面的事务点,继续执行
  10. ROLLBACK [WORK] TO SAVEPOINT xxx
  11. end catch
  12. --其他代码

发布了416 篇原创文章 · 获赞 135 · 访问量 94万+

在论坛中出现的比较难的sql问题:20(触发器专题2)的更多相关文章

  1. 在论坛中出现的比较难的sql问题:46(日期条件出现的奇怪问题)

    原文:在论坛中出现的比较难的sql问题:46(日期条件出现的奇怪问题) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有 ...

  2. 在论坛中出现的比较难的sql问题:45(用户在线登陆时间的小时、分钟计算问题)

    原文:在论坛中出现的比较难的sql问题:45(用户在线登陆时间的小时.分钟计算问题) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. ...

  3. 在论坛中出现的比较难的sql问题:44(触发器专题 明细表插入数据时调用主表对应的数据)

    原文:在论坛中出现的比较难的sql问题:44(触发器专题 明细表插入数据时调用主表对应的数据) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决 ...

  4. 在论坛中出现的比较难的sql问题:42(动态行转列 考勤时间动态列)

    原文:在论坛中出现的比较难的sql问题:42(动态行转列 考勤时间动态列) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

  5. 在论坛中出现的比较难的sql问题:41(循环替换 循环替换关键字)

    原文:在论坛中出现的比较难的sql问题:41(循环替换 循环替换关键字) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

  6. 在论坛中出现的比较难的sql问题:40(子查询 销售和历史库存)

    原文:在论坛中出现的比较难的sql问题:40(子查询 销售和历史库存) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有 ...

  7. 在论坛中出现的比较难的sql问题:39(动态行转列 动态日期列问题)

    原文:在论坛中出现的比较难的sql问题:39(动态行转列 动态日期列问题) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉 ...

  8. 在论坛中出现的比较难的sql问题:38(字符拆分 字符串检索问题)

    原文:在论坛中出现的比较难的sql问题:38(字符拆分 字符串检索问题) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得 ...

  9. 在论坛中出现的比较难的sql问题:37(动态行转列 某一行数据转为列名)

    原文:在论坛中出现的比较难的sql问题:37(动态行转列 某一行数据转为列名) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

  10. 在论坛中出现的比较难的sql问题:36(动态行转列 解析json格式字符串)

    原文:在论坛中出现的比较难的sql问题:36(动态行转列 解析json格式字符串) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

随机推荐

  1. 制作 python解释器

    https://www.zhihu.com/tardis/sogou/qus/27286136

  2. word: 插入或修改文字时后面的字消失 解决办法

    在编辑Word文档中的文字时,我们有时需要插入或修改文字,可是在插入或修改时会发现改动处后面的文字会消失.比如插入或修改3个字,后面的文字随之也会消失3个,这时该怎么办呢? 点击-“文件”-“选项”- ...

  3. idea 配置文件中文显示问题

    配置文件中的中文,有时候会显示异常,因此需要修改文件编码格式修改.下面红框位置需要勾选上.

  4. 一起玩"Docker"之1——Ubuntu配置安装Docker运行环境并安装(Ubuntu、Centos)镜像

    Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Li ...

  5. Qt编写气体安全管理系统18-数据库设置

    一.前言 作为一个管理系统,数据库肯定是不可或缺的,Qt内置的sqlite数据库已经是够用的,而且本人亲测数据量能支持亿级别,而不是像网上很多人说的千万级别,我模拟过一亿多条数据,依然能够很好的查询, ...

  6. Cheng MeiChun团队的技术支持

    本网页为Cheng MeiChun团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:1505478990 邮箱:1505478990@qq.com

  7. Spring MVC 保存并获取属性参数

    在开发控制器的时候,有时也需要保存对应的数据到这些对象中去,或者从中获取数据.而Spring MVC给予了支持,它的主要注解有3个:@RequestAttribute.@SessionAttribut ...

  8. CentOS "libc.so.6: version 'GLIBC_2.14' not found"解决方法,同理'GLIBC_2.15' not found"

    出现"libc.so.6: version 'GLIBC_2.14' not found"问题,是由于glibc版本过低,升级glibc即可. 由于CentOS系统RPM源目前gl ...

  9. EasyNVR是怎么做到Web浏览器播放RTSP摄像机直播视频延时控制在一秒内的

    背景说明 由于互联网的飞速发展,传统安防摄像头的视频监控直播与互联网直播相结合也是大势所趋.传统安防的直播大多在一个局域网内,在播放的客户端上也是有所限制,一般都是都需要OCX Web插件进行直播.对 ...

  10. vue 的反向代理

    情景描述: 原本的vue打包文件是放在.net core 项目的www文件夹下去发布的.这样运行没问题,但是公司领导让服务器单独部署vue,前后端要完全分离.然后这样就出问题了,有一个上传接口的地址一 ...