我创建了AFTER INSERT TRIGGER
现在,如果在执行Trigger时发生错误,则为任何情况。它不应该在触发表上影响插入操作。
如果在触发器中发生任何ERROR,则应该忽略它。
我用过
BEGIN TRY
END TRY
BEGIN CATCH
END CATCH
但它会在触发表
上提供以下错误消息并回滚插入操作触发器执行期间出错。批次已经 已中止,用户事务(如果有)已回滚。
答案 0 :(得分:4)
有趣的问题。默认情况下,设计触发器,如果它们失败,则会回滚触发它的命令。因此,无论何时执行触发器,都存在活动事务,无论外部是否存在明确的BEGIN TRANSACTION。并且BEGIN / TRY内部触发器也不起作用。你的最佳做法是不要在可能失败的触发器中编写任何代码 - 除非希望也使得触发语句失败。
在这种情况下,为了抑制这种行为,有一些解决方法。
选项A(丑陋的方式):
由于事务在触发开始时处于活动状态,您只需COMMIT
它并继续执行触发命令:
CREATE TRIGGER tgTest1 ON Test1 AFTER INSERT
AS
BEGIN
COMMIT;
... do whatever trigger does
END;
请注意,如果触发代码中存在错误,则仍会产生错误消息,但Test1
表中的数据会安全插入。
选项B(也很难看):
您可以将代码从触发器移动到存储过程。然后从实现BEGIN/TRY
的Wrapper SP调用该存储过程,最后从触发器调用Wrapper SP。如果在逻辑中需要在INSERTED
表中移动数据可能有点棘手(现在在SP中) - 可能使用一些临时表。
<强> SQLFiddle DEMO 强>
答案 1 :(得分:2)
你不能,任何解决它的尝试都是蛇油。没有任何数量的TRY / CATCH或@@ ERROR检查可以解决这个基本问题。
如果你想使用紧密耦合的触发器,那么你必须购买由耦合引起的较低的可用性。
如果要保留可用性(即INSERT成功),则必须放弃耦合(删除触发器)。您必须在提交 INSERT后启动的单独事务中执行您计划在触发器中执行的所有处理。一个SQL代理作业轮询表中新插入的行,Service Broker启动的过程甚至应用程序层步骤都符合要求。
答案 2 :(得分:0)
接受的答案的选项A给了我以下错误:“事务在触发器中结束。批处理已中止。”。我通过使用下面的SQL规避了这个问题。
CREATE TRIGGER tgTest1 ON Test1 AFTER INSERT
AS
BEGIN
SET XACT_ABORT OFF
BEGIN TRY
SELECT [Column1] INTO #TableInserted FROM [inserted]
EXECUTE sp_executesql N'INSERT INTO [Table]([Column1]) SELECT [Column1] FROM #TableInserted'
END TRY
BEGIN CATCH
END CATCH
SET XACT_ABORT ON
END