【问题标题】:Update trigger firing after insert插入后更新触发器触发
【发布时间】:2021-03-08 14:10:44
【问题描述】:

我在表DEP_MARCHE 上创建了一个AFTER UPDATE 触发器,它将在我的审计表AuditDepMarche 中插入两行:一行用于旧值(来自虚拟表DELETED),第二行包含新值DEP_MARCHE 的所有列的值(来自虚拟表INSERTED)(DEP_MARCHEAuditDepMarche 具有相同的结构)。我还创建了一个AFTER INSERT 触发器,它在我的审计表中添加了一行。

问题是当我在DEP_MARCHE 中插入一些东西时,AFTER UPDATE 触发器被触发,因此三行被添加到我的审计表中(一行由AFTER INSERT 触发器添加,另外两行由@987654333 @触发器)

我在互联网上搜索,我找到的解决方案是:为两个 (AFTER INSERT, UPDATE) 创建一个触发器并在虚拟表 DELETED 上测试,如果它是空的,那么我在插入触发器之后运行查询,否则我运行更新后触发器的查询,类似这样(但它对我不起作用):

CREATE TRIGGER foo_AlteredRecord 
ON [dbo].[Foo]
AFTER INSERT, UPDATE
AS
BEGIN
    DECLARE @DelCount int;
    DECLARE @InsCount int;

    SELECT @InsCount = COUNT(Col1) FROM INSERTED;
    SELECT @DelCount = COUNT(Col1) FROM DELETED;

    IF @InsCount > 0 AND @DelCount = 0
    BEGIN
        -- At least 1 row inserted. Your Insert Trigger logic here
    END
    ELSE IF @DelCount > 0 AND @InsCount > 0
    BEGIN
        -- old row deleted, new row inserted; both indicates an update.
        -- your update logic here.  
    END
END

在我的代码中实现了这个逻辑之后,每当我在DEP_MARCHE 表中插入一些东西时,它开始在我的审计表中添加不是 3 行而是 5 行(一行用于插入触发器,两行;旧& 新值,重复 => 4 行)

这是我的代码,我将不胜感激

Drop trigger if exists DepMarcheAudit_UPDATE_INSERT
go
CREATE TRIGGER DepMarcheAudit_UPDATE_INSERT
ON DEP_MARCHE
AFTER UPDATE, INSERT
AS
BEGIN

   Declare @DelCount int;
   Declare @InsCount int;

   SELECT @InsCount = Count(*) FROM INSERTED;
   SELECT @DelCount = Count(*) FROM DELETED;

 -----------AFTER UPDATE TRIGGER TRANSACTIONS---------
IF @InsCount > 0 AND @DelCount > 0
   BEGIN
   DECLARE @AUDIT_OPERATION_OLD VARCHAR(50)
   SET @AUDIT_OPERATION_OLD = 'mise à jour (Old values)'

   DECLARE @AUDIT_OPERATION_NEW VARCHAR(50)
   SET @AUDIT_OPERATION_NEW = 'mise à jour (New values)'

   declare @StartTime datetimeoffset(7) = sysdatetimeoffset();

   INSERT INTO [dbo].[DepMarcheAudit](
   [CODE_MARCHE]
   ,[AUDIT_OPERATION_TYPE]
   ,[AUDIT_OPERATION_DATE]
   ,[AUDIT_OPERATION_TIME]
   ,[AUDIT_ID_USER]
         ,[LIBELLE_MARCHE]
         ,[CODE_FOURNISSEUR]
         ,[NUMERO_MARCHE]
         ,[OBSERVATION_MARCHE]
         ,[CODE_NATURE]
         ,[CODE_AO]
         ,[DOC_CONTRAT]
         ,[IS_DEPENSE_SIMPLIFIEE],
         [startTime]
         )
   SELECT 
   [CODE_MARCHE]
   ,@AUDIT_OPERATION_OLD
   ,GETDATE()
   ,(CONVERT([time],getdate(),0))
   ,HOST_NAME()
         ,[LIBELLE_MARCHE]
         ,[CODE_FOURNISSEUR]
         ,[NUMERO_MARCHE]
         ,[OBSERVATION_MARCHE]
         ,[CODE_NATURE]
         ,[CODE_AO]
         ,[DOC_CONTRAT]
         ,[IS_DEPENSE_SIMPLIFIEE]
         ,@StartTime
   FROM DELETED; 

   INSERT INTO [dbo].[DepMarcheAudit](
   [CODE_MARCHE]
   ,[AUDIT_OPERATION_TYPE]
   ,[AUDIT_OPERATION_DATE]
   ,[AUDIT_OPERATION_TIME]
   ,[AUDIT_ID_USER]
         ,[LIBELLE_MARCHE]
         ,[CODE_FOURNISSEUR]
         ,[NUMERO_MARCHE]
         ,[OBSERVATION_MARCHE]
         ,[CODE_NATURE]
         ,[CODE_AO]
         ,[DOC_CONTRAT]
         ,[IS_DEPENSE_SIMPLIFIEE]
         ,[startTime]
         )



   SELECT 



   [CODE_MARCHE]
   ,@AUDIT_OPERATION_NEW
   ,getdate()
   ,(CONVERT([time],getdate(),0))
   ,HOST_NAME()
         ,[LIBELLE_MARCHE]
         ,[CODE_FOURNISSEUR]
         ,[NUMERO_MARCHE]
         ,[OBSERVATION_MARCHE]
         ,[CODE_NATURE]
         ,[CODE_AO]
         ,[DOC_CONTRAT]
         ,[IS_DEPENSE_SIMPLIFIEE]
         ,@StartTime
   FROM INSERTED;
   END

--------------------AFTER INSERT TRIGGER TRANSACTION-----------------------------
ELSE IF @InsCount > 0 AND @DelCount = 0
   
   BEGIN
   
   DECLARE @AUDIT_OPERATION VARCHAR(50)
   SET @AUDIT_OPERATION = 'Insertion'
   INSERT INTO [dbo].[DepMarcheAudit](
   [CODE_MARCHE]
   ,[AUDIT_OPERATION_TYPE]
   ,[AUDIT_OPERATION_DATE]
   ,[AUDIT_OPERATION_TIME]
   ,[AUDIT_ID_USER]
         ,[LIBELLE_MARCHE]
         ,[CODE_FOURNISSEUR]
         ,[NUMERO_MARCHE]
         ,[OBSERVATION_MARCHE]
         ,[CODE_NATURE]
         ,[CODE_AO]
         ,[DOC_CONTRAT]
         ,[IS_DEPENSE_SIMPLIFIEE]
         ,[startTime])

         SELECT 

   [CODE_MARCHE]
   ,@AUDIT_OPERATION
   ,GETDATE()
   ,(CONVERT([time],getdate(),0))
   ,HOST_NAME()
   ,[LIBELLE_MARCHE]
   ,[CODE_FOURNISSEUR]
   ,[NUMERO_MARCHE]
   ,[OBSERVATION_MARCHE]
   ,[CODE_NATURE]
   ,[CODE_AO]
   ,[DOC_CONTRAT]
   ,[IS_DEPENSE_SIMPLIFIEE]
   , sysdatetimeoffset()
FROM INSERTED; 

END
END
GO

【问题讨论】:

  • 如果INSERTUPDATE 需要不同的逻辑,最好创建单独的触发器。
  • 照拉努的建议去做。将两个触发器分开,一个用于 AFTER INSERT,另一个用于 AFTER UPDATE。这将为您简化事情,并让任何人事后进行调整都可以管理。
  • 别忘了添加一个 SET NOCOUNT ON。
  • 你有插入触发器和插入和更新触发器吗?我看不出你们还有什么被解雇的。
  • @Larnu 一开始我创建了单独的触发器,然后我也遇到了问题:更新触发器总是在插入后触发

标签: sql-server triggers


【解决方案1】:

您可以对插入、更新和删除使用一个触发器,因为您对所有人执行相同的操作。唯一的区别似乎是关于它是插入、更新(之前)、更新(之后)或删除的消息。我没有看到删除,但我将其包括在内,因为它没有额外的工作。

如果是删除,则从 INSERTED 中选择不会向审计表中插入任何内容。如果是插入,则从 DELETED 中选择将不会向审计表中插入任何内容。如果是更新,则两个插入都将插入到审计表中。

CREATE TRIGGER DepMarcheAudit_UPDATE_INSERT_DELETE
ON DEP_MARCHE
AFTER UPDATE, INSERT, DELETE
AS
BEGIN

    SET NOCOUNT ON

    DECLARE @DelCount int;
    DECLARE @InsCount int;

    SELECT @InsCount = Count(*) FROM INSERTED;
    SELECT @DelCount = Count(*) FROM DELETED;

    IF @InsCount = 0 AND @DelCount = 0 RETURN

    DECLARE @AUDIT_OPERATION_OLD VARCHAR(50);
    DECLARE @AUDIT_OPERATION_NEW VARCHAR(50);

    IF @InsCount > 0 AND @DelCount > 0 
    BEGIN
       SET @AUDIT_OPERATION_OLD = 'Update (Old values)';
       SET @AUDIT_OPERATION_NEW = 'Update (New values)';
    END
    ELSE IF @InsCount > 0
    BEGIN
       SET @AUDIT_OPERATION_OLD = NULL;
       SET @AUDIT_OPERATION_NEW = 'Insert (New values)';
    END
    ELSE
    BEGIN
       SET @AUDIT_OPERATION_OLD = 'Delete (Old values)';
       SET @AUDIT_OPERATION_NEW = NULL;
    END;

    INSERT INTO [dbo].[DepMarcheAudit](
       [CODE_MARCHE]
       ,[AUDIT_OPERATION_TYPE]
       ...
       )
    SELECT 
       [CODE_MARCHE]
       ,@AUDIT_OPERATION_OLD
       ...
    FROM DELETED; 

    INSERT INTO [dbo].[DepMarcheAudit](
       [CODE_MARCHE]
       ,[AUDIT_OPERATION_TYPE]
       ...
       )
    SELECT 
       [CODE_MARCHE]
       ,@AUDIT_OPERATION_NEW
       ...
    FROM INSERTED; 

    RETURN;

END

如果其他触发器是多余的,请记得删除或禁用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多