Сравнение полей в триггере - PullRequest
2 голосов
/ 22 октября 2010

Итак, я создал триггер, который сравнивает обновления до и после и определяет, изменились ли конкретные поля, указанные в предложении where.Если это так, я вставляю снимок предыдущей информации в таблицу истории.

Проблема заключается в том, что поле создается с нулевыми значениями (с учетом бизнес-правил, оно на законных основаниях равно нулю) и когда выполняется обновлениеневозможно оценить, что строка не равна нулевому значению.Я хочу зафиксировать, что он был отправлен нам пустым, а затем заполнен.

Какой подход следует использовать для сравнения с пустыми полями, не влияя на производительность?


Это для SQL Server2005

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;

1 Ответ

3 голосов
/ 22 октября 2010

К сожалению, вы действительно должны использовать дозорные значения

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

К сожалению, магии нет: вам нужно сравнить все значения, чтобы увидеть различия.

Сказав это, вы касаетесь только таблиц INSERTED и DELETED, так что, как бы плохо это ни было, главная таблица не трогается. Если у вас нет обновления, которое влияет на 10000 с, если строки, оно будет работать нормально.

Вы также можете использовать ИЛИ, но это громоздко

(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

...