【问题标题】:Comparing fields in a trigger比较触发器中的字段
【发布时间】:2010-10-22 17:57:57
【问题描述】:

所以我创建了一个触发器,用于比较更新前后的内容,并确定 where 子句中指定的特定字段是否已更改。如果是这样,我将先前信息的快照插入到历史表中。

问题是当字段创建时使用空值(根据业务规则,它是合法的空值)并且在进行更新时,它无法评估字符串不等于空值。我想捕捉到它是空的,后来又被填充了。

我应该使用什么方法来比较空字段而不影响性能?


这适用于 SQL Server 2005

CREATE TRIGGER [prj].[TRG_Master_Projection_Upd_History] ON [prj].[Master_Projections]
AFTER UPDATE
AS
    SET NOCOUNT ON -- Prevents the error that gets thrown after inserting multiple records 
                   -- if multiple records are being updated

BEGIN


INSERT INTO prj.History_Projections (ProjectionID, Cancelled, Appeal, Description, Response_PatternID, 
                                     Proj_Mail_date, [3602_Mail_Date], Proj_Qty, [3602_Qty], Proj_Resp_Rate,
                                     Bounce_Back, Nickels, Kits, Oversized_RE, ChangeComments, 
                                     Modification_Process, Modification_Date, Modification_User)
    SELECT D.ProjectionID, D.Cancelled, D.Appeal, D.Description, D.Response_PatternID, D.Proj_Mail_Date,
            D.[3602_Mail_Date], D.Proj_Qty, D.[3602_Qty], D.Proj_Resp_Rate, D.Bounce_Back, D.Nickels, D.Kits,
            D.Oversized_RE, D.ChangeComments, D.Modification_Process, D.Modification_Date, D.Modification_User
       FROM deleted as D
    JOIN inserted as I
         ON D.ProjectionID = I.ProjectionID
      WHERE (I.Cancelled <> D.Cancelled
          OR I.Appeal <> D.Appeal
          OR I.Description <> D.Description
          OR I.Response_PatternID <> D.Response_PatternID
          OR I.Proj_Mail_Date <> D.Proj_Mail_Date
          OR I.[3602_Mail_Date] <> D.[3602_Mail_Date]
          OR I.Proj_Qty <> D.Proj_Qty
          OR I.[3602_Qty] <> D.[3602_Qty]
          OR I.Proj_Resp_Rate <> D.Proj_Resp_Rate
          OR I.Bounce_Back <> D.Bounce_Back
          OR I.Nickels <> D.Nickels
          OR I.Kits <> D.Kits
          OR I.Oversized_RE <> D.Oversized_RE )
END;
SET NOCOUNT OFF;

【问题讨论】:

    标签: sql-server sql-server-2005 performance null history


    【解决方案1】:

    不幸的是,你真的必须使用哨兵值

    ISNULL(I.Response_PatternID, 0) <> ISNULL(D.Response_PatternID, 0)
    

    不幸的是,没有魔法:您必须比较每个值才能看到任何差异。

    也就是说,您只触摸 INSERTED 和 DELETED 表,如此糟糕,主表没有被触及。除非您有影响 10000 行的更新,否则它将运行正常。

    你也可以使用 OR ,但这很麻烦

    (I.Response_PatternID <> D.Response_PatternID OR I.Response_PatternID IS NULL AND I.Response_PatternID IS NOT NULL OR I.Response_PatternID IS NOT NULL AND I.Response_PatternID IS NULL) 
    

    我会坚持使用 ISNULL 以避免 COALESCE 出现微妙的数据类型问题

    【讨论】:

    • 像魅力一样工作。不确定合并是否是一种选择,但这似乎排除了它。谢谢!
    • 另外,使用您的 isnull,确保第二个值不会出现。例如,您的身份都从 1 开始。然后在您的 isnulls 中,您可以输入 -9999 之类的内容。这样,如果记录更新为 id 为零,您将获得正确的逻辑。
    猜你喜欢
    • 1970-01-01
    • 2020-02-11
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    相关资源
    最近更新 更多