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

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

只要用触发器肯定会操作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
AS

declare @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)
begin
 goto TheEnd; --TheEnd是脚本结尾处的结束标签
end
else if exists (select 1 from inserted) and exists (select 1 from deleted)
begin
   set @IsUpdate=1; -- 如果两张虚表都有数据表示执行的是update操作
end
else if exists (select 1 from inserted) and not exists (select 1 from deleted)
begin
   set @IsInsert=1; -- 只有inserted有数据表示是执行insert语句触发的
end
else
begin
   set @IsDelete=1;
end

begin try

declare @newValue varchar(100);
declare @oldValue varchar(100);

if @IsInsert=1 or @IsUpdate=1
begin
    --获取新修改的Name字段
    SELECT  @tempValue = Name FROM inserted;
begin

if @IsUpdate=1 or @IsDelete=1
begin
    --获取修改或删除前的Name字段
    SELECT  @oldValue = Name FROM deleted;
end

-- 其它业务处理......

end try
begin catch
  begin try
  declare @Error varchar(200);
  set @Error=‘TgrError:‘+cast(ERROR_LINE() as varchar)+‘_‘ +isnull(ERROR_MESSAGE(),‘‘);
  -- 将@Error的值可以记录到一个执行的日志表中
  end try
  begin catch
  end catch
end catch

TheEnd:

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

原文地址:https://www.cnblogs.com/Taburensheng/p/9706102.html

时间: 2024-09-28 18:31:01

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

plsql登录数据库,报错“ora-12541:TNS:无监听程序”错误

前一段时间,由于需要修改了数据库的主机名,当时修改数据库主机名使用即时生效的方法修改的,昨天公司停电,重启数据库,登录plsql就报错了 "ora-12541:TNS:无监听程序"错误 主要原因就是由于我修改了主机名,导致配置文件里面的主机名和实际的主机名不相同. 需要修改配置文件 /opt/oracle/product/10.2.0/db_1/network/admin这个路径下的listener.ora  tnsnames.ora这两个配置文件,如果有一个就修改一个,有两个就修改两

SQL SERVER性能分析--死锁检测数据库阻塞语句

工作中数据库经常出现内存,找了篇文章 参照CSDN,中国风(Roy)一篇死锁文章 阻塞:其中一个事务阻塞,其它事务等待对方释放它们的锁,同时会导致死锁问题. 整理人:中国风(Roy) 参照Roy_88的博客 http://blog.csdn.net/roy_88/archive/2008/07/21/2682044.aspx 日期:2008.07.20 ************************************************************************

sql server 复制表从一个数据库到另一个数据库

sql server 复制表从一个数据库到另一个数据库 /*不同服务器数据库之间的数据操作*/ --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 ' --查询示例 select * from ITSV.数据库名.dbo.表名 --导入示例 select * into 表 f

sql server 本地复制订阅 实现数据库服务器 读写分离(转载)

转载地址:http://www.cnblogs.com/echosong/p/3603270.html 再前段echosong 写了一遍关于mysql 数据同步实现业务读写分离的文章,今天咱们来看下SQL Server的复制订阅实现数据的读写分离 比起mysql的复制,SQL server 复制相对强大 一. 名词解释 1.复制的 机构组成(类比报纸流通): 1).发布服务器(报社出版) 生产维护数据源,审阅所有出版数据的更改 发送给 分发服务器(邮局) 2).分发服务器 (邮局) 分发服务器包

sql server 本地复制订阅 实现数据库服务器 读写分离

原文:sql server 本地复制订阅 实现数据库服务器 读写分离 再前段echosong 写了一遍关于mysql 数据同步实现业务读写分离的文章,今天咱们来看下SQL Server的复制订阅实现数据的读写分离 比起mysql的复制,SQL server 复制相对强大 一. 名词解释 1.复制的 机构组成(类比报纸流通): 1).发布服务器(报社出版) 生产维护数据源,审阅所有出版数据的更改 发送给 分发服务器(邮局) 2).分发服务器 (邮局) 分发服务器包括分发数据库,并且存储元数据.历史

SQL Server不停机移动镜像数据库

SQL Server数据库镜像是对于数据库可用性的软件解决方案.镜像在每个数据库级别被部署,并只能在完整恢复模式下工作.由于磁盘空间的问题,需要移动镜像数据库到一个不同的位置.我们想不停机.不破坏镜像来完成这个任务.需要在不同的环境做测试. 对于启用了数据库镜像的数据库的文件移动,我们只有有限的选择.常规方法如下: 破坏数据库镜像会话,通过使用Alter database或Attach Detach移动在线数据库文件到一个新的位置. 备份数据库,并在镜像服务器上恢复备份,然后重建镜像. 技术上来

sql server 2008 R2 压缩备份数据库

今天需要把一个省外项目的数据库从服务器上备份.拷贝到本机(跨地域传输数据库备份文件). 连上VPN,通过远程桌面连接,连接上服务器,发现数据库文件已经有20G以上大小了. 文件太大,公司网络也不稳定,根本不可能通过网络传输过来. 于是,把数据库的恢复模式由"完整"模式设置为"简单"模式,接着收缩数据库, 数据库瞬间由20G变成1G多点. 在SSMS中,新建查询窗口,执行数据库备份语句: --定义变量,把备份数据库的QL脚本赋值给变量 declare @SqlBack

SQL Server 2008 R2 下移动数据库的存储位置

使用场景:1. 该数据库增长的较大,存储磁盘空间不足:   2. 在特定情况下该数据库需要移动到另外一块磁盘上(呵呵...我的情况就是之前的磁盘要还给别人) 步骤: 1. 新建查询 SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('yourDataBaseName'); GO 查看到结果会看到数据库主文件以及日志的名称和物理存储的地址名称   2.新建查询 use master alter da

如何进行数据库,比如ORACLE,SQL SERVER的逆向工程,将数据库导入到PowerDesigner中

如何进行数据库,比如ORACLE,SQL SERVER的逆向工程,将数据库导入到PowerDesigner中 Oracle的反向工程就是指将Oracle中的数据库,当然也可以是SQL Server中的数据库导入到PD中,这个需要建立一个数据库的链接,然后进行逆向工程的操作. 第一步:建立数据库的链接: PowerDesigner建立与数据库的连接,以便生成数据库和从数据库生成到PD中.[Oracle 10G版] PowerDesigner建立与数据库的连接,以便生成数据库和从数据库生成到PD中.