比较触发器中的字段

发布于 2024-09-28 19:16:41 字数 2014 浏览 2 评论 0原文

因此,我创建了一个触发器,用于比较更新前后的情况,并确定 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;

So I've created a trigger that compares update before and after and determines if specific fields, specified in the where clause, have changed. If so, I insert a snapshot of the prior information into a history table.

The problem is when the field is created with null values (given the business rules, it is legitimately null) and when an update is made, it is unable to evaluate that the string is not equal to the null value. I want to capture that it was sent to us empty and later filled in.

What approach should I use to compare to null fields without impacting performance?

This is for 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冧九 2024-10-05 19:16:41

不幸的是,您确实必须使用哨兵值。不幸的

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 出现微妙的数据类型问题

Unfortunately, you really have to use sentinel values

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

There is no magic unfortunately: you have to compare every value to see any differences.

Saying that, you only touch the INSERTED and DELETED tables so as bad as this is, the main table is not touched. Unless you have update that affect 10000s if rows, it will run OK.

You can use OR too to but this is cumbersome

(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) 

I'd stick with ISNULL to avoid subtle datatype issues with COALESCE

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文