Sql Server 因为触发器问题导致数据库更新报错“在触发器执行过程中引发了错误,批处理已中止”的问题处理...

news/2024/7/3 2:40:58

       在维护一个非常旧的项目时,由于该项目版本已经非常老了,而且在客户现场运行的非常稳定,更要命的是本人目前没有找到该项目的代码,为了处理一个新的需求而且还不能修改程序代码,于是决定从数据库入手,毕竟该项目数据库的脚本还是可以操作的,那就在数据流的必经之路上拦截数据处理业务就是了,于是决定在一张业务表上加一个触发器,关于触发器的基础这里就不多说了,网上一搜一大堆,其实就是一张表的数据行被操作以后会针对被操作的数据行执行一段存储过程脚本,只不过这个存储过程比较特殊罢了,是专门侦听对表的操作然后由系统调用的而已……

        只要用触发器肯定会操作inserted和deleted两张表,大家切记在写t-sql业务操作之前一定要判断这两张虚表中是不是有数据,如果不判断直接往下执行就有可能报“在触发器执行过程中引发了错误,批处理已中止,用户事务(如果有)已回滚”的错误,本人就吃了一个这样的亏;触发器刚加上前几天运行的挺正常,等过几天发现有些针对这张业务表执行其它业务操作一执行就报前面所说的错误,查了n久发现业务操作中执行了一个update语句,而这个update语句的where条件过滤后其实一条符合where条件的数据都没有,这样就导致执行触发器的时候 deleted和inserted两张虚表中是没有数据的,再操作下去就报错了,触发器一报错正常的原来好用业务也报错了……

解决方法很简单,在触发器的结尾加一个结束标签TheEnd,然后在触发器入口判断两张虚表(inserted和deleted)是否有数据,如果都没有数据直接跳转到结束标签TheEnd处不处理就是了,只有有数据的时候才执行业务处理,大概代码如下,看红色加粗部分:

create trigger [dbo].[Tgr_MyTable_InsertUpdate] --触发器名
on [dbo].[MyTable] --MyTable是实际业务表名for insert,update
ASdeclare @IsUpdate bit;
declare @IsInsert bit;
declare @IsDelete bit;set @IsDelete=-1; 
set @IsInsert=-1;
set @IsUpdate=-1;--这个判断很关键,如果没有数据那就别处理了,直接跳转到末尾
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
begingoto TheEnd; --TheEnd是脚本结尾处的结束标签
end
else if exists (select 1 from inserted) and exists (select 1 from deleted)
beginset @IsUpdate=1; -- 如果两张虚表都有数据表示执行的是update操作
end
else if exists (select 1 from inserted) and not exists (select 1 from deleted)
beginset @IsInsert=1; -- 只有inserted有数据表示是执行insert语句触发的
end
else
beginset @IsDelete=1;
endbegin trydeclare @newValue varchar(100);
declare @oldValue varchar(100);if @IsInsert=1 or @IsUpdate=1
begin--获取新修改的Name字段SELECT  @tempValue = Name FROM inserted;
beginif @IsUpdate=1 or @IsDelete=1
begin--获取修改或删除前的Name字段SELECT  @oldValue = Name FROM deleted;
end-- 其它业务处理......end try
begin catchbegin trydeclare @Error varchar(200);set @Error='TgrError:'+cast(ERROR_LINE() as varchar)+'_' +isnull(ERROR_MESSAGE(),'');-- 将@Error的值可以记录到一个执行的日志表中end trybegin catchend catch
end catchTheEnd:

就是这么简单,以上排查问题结果分享给其它小伙伴,希望大家别再走我的弯路

转载于:https://www.cnblogs.com/Taburensheng/p/9706102.html


http://lihuaxi.xjx100.cn/news/236169.html

相关文章

ajax访问其他电脑的文件,解决ajax不能访问本地文件问题(利用js跨域原理)

博主自己在开发一个无后台,只有前台的查询系统时,遇到一个困难,如何利用Ajax读取自己的本地json文件,百度、谷歌了下,发现大部分文章都是在说修改浏览器参数,但是自己想想,用户在使用时&#xf…

css:z-index

针对position: absolute;解决position:relative;z-index固定定位层级显示问题转载于:https://blog.51cto.com/13507333/2352775

Java数组合并,完成排序,从时间复杂度,和空间复杂度考虑

2019独角兽企业重金招聘Python工程师标准>>> 提供方法,直接调用,支持任意个数组的合并成一个数组,并且完成排序,每个数组元素个数不定。需要提供两个方法,分别做到时间复杂度最低、空间复杂度最低。并说明两…

服务器操作系统安全更新,服务器操作系统安全更新

服务器操作系统安全更新 内容精选换一换使用弹性云服务器或者外部镜像文件创建私有镜像时,必须确保操作系统中已安装UVP VMTools,使新发放的云服务器支持KVM虚拟化,同时也可以提升云服务器的网络性能。如果不安装UVP VMTools,云服…

Redis的集群模式

集群 即使使用哨兵,此时的Redis集群的每个数据库依然存有集群中的所有数据,从而导致集群的总数据存储量受限于可用存储内存最小的数据库节点,形成木桶效应。由于Redis中的所有数据都是基于内存存储,这一问题就尤为突出了尤其是当使…

综合布线系统入门及应用(二)

一、工程材料用量估计 1、信息模块及水晶头用量统计 信息插座与工位数量1:1,在增加5%的余量 跳线:一般需要2条,工位信息面板到设备,交换机到配线架,每根条线2个水晶头,预留10%-15%。 2、线槽用量统计 根据办…

JDBC

当我们在写一个程序时,会产生很多有用的数据,我们的注册信息,我们的购物车,我们的记录下来的一些信息,但我们知道程序运行在内存中,当断电后,运行时产生的数据全都会消失了,那怎么办…

力扣(LeetCode)933

题目地址:https://leetcode-cn.com/probl...题目描述:写一个 RecentCounter 类来计算最近的请求。 它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。 返回从 3000 毫秒前到现在的 ping 数。 任何处于 [t - 3000, …