0

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

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
4

1 回答 1

0

当我看到你的触发器时,我突然想到了一些事情:

  • 您正在执行多个附加更新而不是单个更新(在性能方面,单个更新会更好)。
  • 您的更新语句不受约束(插入/删除的表没有 JOIN 以限制您执行这些附加更新的记录数)。
  • 大部分逻辑感觉应该在应用层而不是数据库中;或者,也许在某些情况下实施方式不同。

一些简单的例子:

  • 插入前应删除“n/a”后缀。
  • 电缆长度绝对值应在插入前完成(使用 CHECK CONSTRAINT 验证不能插入不良数据)。
  • TotalFootage 应该是一个计算列,所以它总是正确的。
  • 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
于 2012-06-06T18:42:06.293 回答