Triggers SQL SErver触发器未正确计算为插入或更新

Triggers SQL SErver触发器未正确计算为插入或更新,triggers,insert,Triggers,Insert,我想要一个触发器来处理更新和插入。触发器中的大多数sql操作都适用于这两种情况。唯一的例外是我用来记录插入和更新的日期和用户名的字段。这就是我所拥有的,但是用于跟踪更新和插入的字段的更新没有正确触发。如果我插入一条新记录,我会得到CreatedBy,CreatedOn,lastedby,lasteddon填充,在CreatedOn之后1秒是lasteddon,这是我不想发生的。当我更新记录时,只有lastedby&lasteddon更改了正确的记录。我将我的全部触发器包括在内,以供参考: SET

我想要一个触发器来处理更新和插入。触发器中的大多数sql操作都适用于这两种情况。唯一的例外是我用来记录插入和更新的日期和用户名的字段。这就是我所拥有的,但是用于跟踪更新和插入的字段的更新没有正确触发。如果我插入一条新记录,我会得到CreatedBy,CreatedOn,lastedby,lasteddon填充,在CreatedOn之后1秒是lasteddon,这是我不想发生的。当我更新记录时,只有lastedby&lasteddon更改了正确的记录。我将我的全部触发器包括在内,以供参考:

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
-- =================================================================================
-- Author:  Paul J. Scipione
-- Create date: 2/15/2012
-- Update date: 6/5/2012
-- Description: To concatenate several fields into a set formatted UnitDescription,
--              to total Span & Loop footages, to set appropriate AcctCode, & track
--              user inserts
-- =================================================================================
IF OBJECT_ID('ProcessCable', 'TR') IS NOT NULL
  DROP TRIGGER ProcessCable
GO
CREATE TRIGGER ProcessCable
ON Cable
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;

-- IF TRIGGER_NESTLEVEL() > 1 RETURN

IF ((SELECT TRIGGER_NESTLEVEL()) > 1 )
  RETURN
ELSE
  BEGIN
  -- record user and date of insert or update
  IF EXISTS (SELECT * FROM DELETED)
    UPDATE Cable SET LastEditedOn = getdate(), LastEditedBy = REPLACE(user_name(), 'GRTINET\', '')
  ELSE IF NOT EXISTS (SELECT * FROM DELETED)
    UPDATE Cable SET CreatedOn = getdate(), CreatedBy = REPLACE(user_name(), 'GRTINET\', '')

  -- reset Suffix if applicable
  UPDATE Cable SET Suffix = NULL WHERE Suffix = 'n/a'

  -- create UnitDescription value
  UPDATE Cable SET UnitDescription =
    isnull (Type, '') +
    isnull (CONVERT (NVARCHAR (10), Size), '') +
    '-' +
    isnull (CONVERT (NVARCHAR (10), Gauge), '') +
    CASE
      WHEN ExtraTrench IS NOT NULL AND ExtraTrench > 0 THEN
        CASE
          WHEN Suffix IS NULL THEN 'TE' + '(' + CONVERT (NVARCHAR (10), ExtraTrench) + ')'
          ELSE 'TE' + '(' + CONVERT (NVARCHAR (10), ExtraTrench) + ')' + Suffix
        END
      ELSE isnull (Suffix, '')
    END

  -- convert any accidental negative numbers entered
  UPDATE Cable SET Length = ABS(Length)

  -- sum Length with LoopFootage into TotalFootage
  UPDATE Cable SET TotalFootage = isnull(Length, 0) + isnull(LoopFootage, 0)

  -- set proper AcctCode based on Type
  UPDATE Cable SET AcctCode =
    CASE
      WHEN Type IN ('SEA', 'CW', 'CJ') THEN '32.2421.2'
      WHEN Type IN ('BFC', 'BJ', 'SEB') THEN '32.2423.2'
      WHEN Type IN ('TIP','UF') THEN '32.2422.2'
      WHEN Type = 'unknown' OR Type IS NULL THEN 'unknown'
    END
  WHERE AcctCode IS NULL OR AcctCode = ' '

END

END
GO

当我看到你的扳机时,有几件事突然向我袭来:

您正在执行多个附加更新,而不是单次更新性能方面,单次更新会更好。 update语句不受约束。插入/删除的表没有联接,无法限制对其执行这些附加更新的记录数。 这种逻辑的大部分感觉应该在应用层而不是数据库中;或者,在某些情况下,实施方式可能有所不同。 一些快速示例:

插入前应删除n/a后缀。 插入电缆长度绝对值之前,应使用检查约束进行检查,以验证无法插入错误数据。 TotalCutes应为a,因此它始终是正确的。 Type/AcctCode关系似乎应该是外键引用中的列值。 但归根结底,我认为你看到这些意外日期的原因是因为没有限制的更新。在没有解决我上面提到的任何其他问题的情况下,设置审计字段的语句应该更像这样:

UPDATE Cable SET LastEditedOn = getdate(), LastEditedBy = REPLACE(user_name(), 'GRTINET\', '')
FROM Cable
    JOIN deleted on Cable.PrimaryKeyColumn = deleted.PrimaryKeyColumn

UPDATE Cable SET CreatedOn = getdate(), CreatedBy = REPLACE(user_name(), 'GRTINET\', '')
FROM Cable
    JOIN inserted on Cable.PrimaryKeyColumn = inserted.PrimaryKeyColumn
    LEFT JOIN deleted on Cable.PrimaryKeyColumn = deleted.PrimaryKeyColumn
WHERE deleted.PrimaryKeyColumn IS NULL

谢谢你提供我代码其他部分的提示。我尝试了您的连接语法来约束审核字段更新,得到了相同的结果。我正在测试的代码变体中的一个常量是,CreatedOn只在初始插入时设置一次。