首页 > 解决方案 > 收到错误“回滚事务请求没有相应的开始事务”

问题描述

我正在尝试创建一个触发器,由于某种原因,第二个 if 语句破坏了我的代码。

如果我删除第二个 if 语句,代码将起作用。我得到的错误是:

回滚事务请求没有对应的开始事务

我的代码:

create trigger insertemployee 
on jobinsailing 
after insert 
as 

BEGIN TRANSACTION   

declare @sailingID        int, 
        @employeeID       char(9), 
        @jobTitle         varchar(10), 
        @sailingStartDate date, 
        @sailingEndDate   date 

select @sailingId = inserted.sailingid, 
       @employeeID = inserted.employeeid, 
       @jobTitle = inserted.jobtitle, 
       @sailingStartDate = sailing.leavingtime, 
       @sailingEndDate = sailing.returntime 
from   inserted 
       inner join sailing 
               on inserted.sailingid = sailing.sailingid 

if exists(select employeeid 
          from   sailing 
                 inner join jobinsailing 
                         on sailing.sailingid = jobinsailing.sailingid 
          where  ( @sailingStartDate <= returntime ) 
                 and ( leavingtime <= @sailingEndDate ) 
                 and employeeid = @employeeID) rollback TRANSACTION; 


else if exists((select sailing.sailingid 
          from   sailing 
                 inner join jobinsailing 
                         on jobinsailing.sailingid = sailing.sailingid 
          where  Datediff(day, @sailingStartDate, sailing.leavingtime) <= 4 
                  or Datediff(day, @sailingEndDate,sailing.leavingtime) <= 4 
                  or Datediff(day, @sailingStartDate,sailing.returntime) <= 4 
                  or Datediff(day, @sailingEndDate,sailing.returntime) <= 4
                  ))  rollback TRANSACTION;

COMMIT TRANSACTION

标签: sqlsql-server

解决方案


条件插入

您要实现的是使用触发器有条件地将记录插入表中。

这通常是一种不好的方法。您的代码(存储过程和/或业务层代码)应确定是否应在插入记录之前先插入记录。触发器并不是最好的工具——它们旨在让您强制执行复杂的约束。

假设你必须使用触发器,那么我建议你使用INSTEAD OF触发器。它们旨在覆盖通常发生的默认插入过程,并允许您插入(或不插入)数据,而不必回滚事务。

多行插入

正如@DaleBurrell 指出的那样,每次插入操作都会执行一次触发器,并且inserted表可以包含多行。最好对触发器进行编码,使其允许多行操作,但您也可以通过将此行添加到触发器的顶部来强制执行单行操作IF (ROWCOUNT_BIG() > 1) ROLLBACK

进一步阅读


推荐阅读