Triggers SQL Server触发器未插入行

Triggers SQL Server触发器未插入行,triggers,sql-server-2008-r2,Triggers,Sql Server 2008 R2,我使用SQL Server 2008 R2 我有一个简单的触发器 CREATE TRIGGER [dbo].[T_Personne_ITrig] ON [dbo].[Personne] FOR INSERT AS BEGIN SET NOCOUNT ON insert into syn_HistoriquePersonne (hpers_Timestamp, Supprime, ID, Nom, Prenom, Champ1, Champ2, Champ3, Ch

我使用SQL Server 2008 R2

我有一个简单的触发器

CREATE TRIGGER [dbo].[T_Personne_ITrig] ON [dbo].[Personne] FOR INSERT AS 
BEGIN
SET NOCOUNT ON 

insert into syn_HistoriquePersonne 
     (hpers_Timestamp, Supprime, ID, Nom, Prenom, Champ1, 
      Champ2, Champ3, Champ4 SiteAssocie)
 select  GETDATE(), 0, ID, Nom, Prenom, Champ1, Champ2, Champ3, 
       Champ4,  SiteAssocie
from inserted
END
它工作正常。问题是,我在一个代码库很糟糕的程序上工作,所以我的老板不想触发任何导致表回滚的事件,即使它失败了。我知道这是不可能的,但他害怕在数据库发生巨大活动时超时。。。反正

所以我搜索了关于在触发器中提交的内容。并将触发器更改为:

CREATE TRIGGER [dbo].[T_Personne_ITrig] ON [dbo].[Personne] FOR INSERT AS 
BEGIN
SET NOCOUNT ON 

COMMIT

insert into syn_HistoriquePersonne 
     (hpers_Timestamp, Supprime, ID, Nom, Prenom, Champ1, 
      Champ2, Champ3, Champ4 SiteAssocie)
select  GETDATE(), 0, ID, Nom, Prenom, Champ1, Champ2, Champ3, 
       Champ4,  SiteAssocie
from inserted
END
但扳机一直在发射信息

事务在触发器中停止,批处理中止

所以我就这样做了:

CREATE TRIGGER [dbo].[T_Personne_ITrig] ON [dbo].[Personne] FOR INSERT AS 
BEGIN
SET NOCOUNT ON 

COMMIT
BEGIN TRAN
insert into syn_HistoriquePersonne 
     (hpers_Timestamp, Supprime, ID, Nom, Prenom, Champ1, 
      Champ2, Champ3, Champ4, SiteAssocie)
 select  GETDATE(), 0, ID, Nom, Prenom, Champ1, Champ2, Champ3, 
       Champ4,  SiteAssocie
 from inserted
 END
它停止了批处理,但似乎从未在我的历史表中插入任何内容。。。我读过关于这个主题的书,我想这应该行得通。但它不

其他人都有过这个问题,我该如何解决


我正在做简单的插入测试来测试我的触发器。

不幸的是,你找错了方向。你不能用那种方式处理交易

如果唯一的问题是插入失败,您可以简单地围绕插入编写一个检查代码。或者只是非常粗略地确保表上的约束准确地反映其用途。但是,由于您还担心导致命令超时的进程的持续时间,因此这不会完全覆盖您(事实上,这会使超时的可能性略微增加)

我所看到的唯一可行的方法是大规模简化insert语句,并将某些内容(所有数据,或者只是时间戳和id?)插入到一个没有约束或索引的保留表中。然后,您将需要一个服务器端进程,该进程将被反复调用以处理暂挂表

由于您的案例似乎只是维护一个历史日志,因此可能有一个选项非常简单,即从historique表中删除所有约束。所有的解决方案都有点脏,但是你老板的要求似乎有点不寻常;在我看来,答案应该是容量规划


我不知道这是否符合您的真实情况,但我希望它能有所帮助。

只要不要在触发器中调用
ROLLBACK
,您就会没事了。不要在触发器中启动新事务。。。触发器应始终在导致其触发的操作的上下文中执行。我不会在触发器中调用回滚,但如果发生超时,应用程序将调用回滚。我知道begin传输不是最佳的,但它确实会停止错误消息。但真正的问题是为什么insert不起作用……但是您在第一个代码段中说:它工作正常-那么,又是什么问题呢??如果有一个超时-你在触发器内无论如何都无法处理它…我知道这可能是我老板的一个愚蠢要求,但他想要的是,如果触发器中发生任何错误,也就是超时,他希望Personne上的初始事务保持完整,而不是回滚。它从未发生过,但他想确定…触发器是作为触发触发器的插入的一部分发生的。您不能在触发器内部编写代码以将其与外部事务隔离。对不起,但我不知道如何用不同的词来表达,你找错了方向,这是不可能的。如果确实希望这两段代码是独立的,请删除触发器,并在应用程序调用的sql中放置一些“立即更新历史记录表”代码。然后,您可以控制放置开始和提交的位置和时间。但是你不能在一个不属于该事务的事务中有一段代码,历史表已经没有任何约束了。但问题是,即使我没有Begin Tran语句,如果我在插入日志表之前在触发器中放入commit,那么插入似乎永远不会工作。。。好像我从来没有调用过insert,我也不明白为什么。如果代码执行了insert,并且应该执行它,我会打印一些内容。但是由于一个未知的原因,没有插入任何内容,我也没有收到任何错误消息。@AlexJean-正如我回答的第一行:你不能玩这样的交易。BEGIN事务和COMMIT事务必须彼此在同一范围内。如果应用程序的SQL命令开始事务,则应用程序的命令必须提交事务。由于您的表上有eno约束等,您无法使它更快,这是您唯一可以做的事情。(试图在您的目标中构建命令超时故障保护是不可能的。)@Alex Jean为什么要在触发器中执行
COMMIT
?Dems是正确的-删除它。它是为了使Personne表上的初始事务“可展开”,以防日志表中的插入失败。