【问题标题】:SQL Server trigger not inserting rowSQL Server 触发器不插入行
【发布时间】:2012-02-16 15:52:43
【问题描述】:

我使用 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

它工作正常。问题是,我在一个代码库很糟糕的程序上工作,所以我的老板不想触发导致表Personne 的回滚,即使它失败了。我知道这真的不太可能,但他害怕在大量数据库活动的情况下超时......无论如何

所以我搜索了有关在触发器中提交的信息。并将触发器更改为:

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

它停止了批处理中止,但它似乎从未在我的历史表中插入任何内容...我阅读了有关该主题的信息,我认为这应该可以工作。但它没有......

其他人已经遇到过这个问题,我该如何解决?

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

【问题讨论】:

  • 只是不要在你的触发器中调用ROLLBACK - 那么你应该没问题。不要在触发器中启动新事务...触发器应始终在导致其触发的操作的上下文中执行。
  • 我不会在我的触发器中调用回滚,但如果发生超时,应用程序会调用。我知道 begin tran 不是最佳的,但它确实停止了错误消息。但真正的问题是为什么插入不起作用......
  • 但是您在第一个代码 sn-p 下说过:它可以正常工作 - 那么问题又是什么?如果有超时 - 无论如何你都无法在触发器内做任何事情来处理......
  • 我知道这可能是我老板的愚蠢要求,但他想要的是,如果触发器中发生任何错误,也就是超时,他希望 Personne 上的初始交易保持不变并且没有回滚。它从未发生过,但他想确定......
  • 触发器作为触发触发器的插入的一部分发生。您不能在触发器内编写代码以将其与外部事务隔离。对不起,但我不知道如何用不同的词来表达,你找错了树,这是不可能的。如果您真的希望这两段代码是独立的,请移除触发器,并在您的应用程序调用的 sql 中放置一些“现在更新历史表”代码。然后,您可以控制放置开始和提交的位置和时间。但是你不能在一个不属于该事务的事务中包含一段代码。

标签: triggers sql-server-2008-r2


【解决方案1】:

不幸的是,你找错了树。你不能这样玩交易。

如果唯一担心的是插入失败,您可以简单地对插入进行检查。或者只是非常彻底地确保表上的约束准确反映它的使用。但是,由于您还担心导致命令超时的过程持续时间,因此这不会完全涵盖您(实际上它会稍微增加超时的可能性)。

我认为唯一可行的方法是大幅简化插入语句,并将某些内容(所有数据,或者只是时间戳和 ID?)插入到没有约束或索引的保存表中。然后,您将需要一个重复调用的服务器端进程来处理您的暂存表。

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

我不知道这是否适合您的真实场景,但我希望它有所帮助。

【讨论】:

  • 历史表已经完全没有约束了。但问题是,即使我没有 Begin Tran 语句,如果我在插入日志表之前在触发器中提交了一个提交,插入似乎永远不会工作......就像我从来没有在全部,我不明白为什么。
  • 如果代码执行插入并且它应该执行它,我跟踪了一些打印。但由于未知原因,没有插入任何内容,我根本没有收到任何错误消息。
  • @AlexJean - 根据我回答的第一行:你不能玩这样的交易。 BEGIN TRANSACTION 和 COMMIT TRANSACTION 必须彼此处于同一范围内。如果应用程序的 SQL 命令开始事务,应用程序的命令必须提交它。由于您的桌子上有 eno 限制等,您不会让它变得更快,这是您唯一可以做的事情。 (试图在你的目标中建立命令超时故障保险是不可能的。)
  • @Alex Jean 你为什么要在触发器中执行COMMIT? Dems 是对的 - 删除它。
  • 它是为了使表 Personne 上的初始事务'unrollbackable',以防日志表中的插入失败。
猜你喜欢
  • 1970-01-01
  • 2013-11-09
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
相关资源
最近更新 更多