Триггер с несколькими рядами - PullRequest
0 голосов
/ 12 апреля 2011

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

CREATE TRIGGER [DT].[trg_LogChanges]
ON [DT].[NewDetails]
FOR UPDATE
AS 

DECLARE
    @TableName VARCHAR(100) ,
    @UpdatedDate smalldatetime ,
    @UpdatedBy uniqueidentifier

SELECT @TableName = 'DT.NewDetails'

IF EXISTS (SELECT 1 FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid)

    IF(SELECT ModifiedDate FROM INSERTED) Is Null
        SET @UpdatedDate = getdate()
    ELSE
        SET @UpdatedDate = (SELECT ModifiedDate FROM INSERTED)

    IF(SELECT ModifiedBy FROM INSERTED) Is Null
        SET @UpdatedBy = '11111111-1111-1111-1111-111111111111'
    ELSE
        SET @UpdatedBy = (SELECT ModifiedBy FROM INSERTED)


IF UPDATE (StatusID)
    BEGIN
        INSERT INTO DT.LogChanges
        (
            ChangeType, TableName, RecordGuid, FieldName
            , OldValue, NewValue, UpdatedBy, UpdatedDate
        )
        SELECT 
            'U', @TableName, d.Guid, 'StatusID'
            , d.StatusID, i.StatusID, @UpdatedBy, @UpdatedDate
        FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid
        WHERE 
            (d.StatusID IS NULL AND i.StatusID IS NOT NULL)
            OR (d.StatusID IS NOT NULL AND i.StatusID IS NULL)
            OR (d.StatusID <> i.StatusID)
    END

Может кто-нибудь предложить какую-либо помощь о том, как это исправить для работы с несколькими строками?Я попытался сделать следующее, добавив SELECT 1 FROM INSERTED, но все равно получаю сообщение об ошибке подзапроса.

CREATE TRIGGER [DT].[trg_LogChanges]
   ON [DT].[NewDetails]
   FOR UPDATE
AS 

DECLARE
    @TableName VARCHAR(100) ,
    @UpdatedDate smalldatetime ,
    @UpdatedBy uniqueidentifier

SELECT @TableName = 'DT.NewDetails'

IF EXISTS (SELECT 1 FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid)

    IF(SELECT ModifiedDate FROM INSERTED) Is Null
        SET @UpdatedDate = getdate()
    ELSE
        SET @UpdatedDate = (SELECT ModifiedDate FROM INSERTED)

    IF(SELECT ModifiedBy FROM INSERTED) Is Null
        SET @UpdatedBy = '11111111-1111-1111-1111-111111111111'
    ELSE
        SET @UpdatedBy = (SELECT ModifiedBy FROM INSERTED)


IF UPDATE (StatusID)
    BEGIN
        IF EXISTS (SELECT 1 FROM INSERTED i
                    INNER JOIN DELETED d
                        on i.Guid = d.Guid
                    WHERE 
                        (d.StatusID IS NULL AND i.StatusID IS NOT NULL)
                        OR (d.StatusID IS NOT NULL AND i.StatusID IS NULL)
                        OR (d.StatusID <> i.StatusID))
        BEGIN
            INSERT INTO DT.LogChanges
            (
                ChangeType, TableName, RecordGuid, FieldName
                , OldValue, NewValue, UpdatedBy, UpdatedDate
            )
            SELECT 
                'U', @TableName, d.Guid, 'StatusID'
                , d.StatusID, i.StatusID, @UpdatedBy, @UpdatedDate
            FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid
            WHERE 
                (d.StatusID IS NULL AND i.StatusID IS NOT NULL)
                OR (d.StatusID IS NOT NULL AND i.StatusID IS NULL)
                OR (d.StatusID <> i.StatusID)
        END
    END

Я искал в Интернете, но, очевидно, мне все еще не хватает правильного способа сделать это.Любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ Я говорил с владельцами бизнеса этого процесса, и они хотят игнорировать обновления в нескольких строках.Есть ли способ добавить IF вокруг всего триггера, чтобы игнорировать его, если записи больше 0?

Спасибо

1 Ответ

2 голосов
/ 12 апреля 2011

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

INSERT INTO DT.LogChanges (ChangeType, TableName, RecordGuid, FieldName, OldValue, NewValue, UpdatedBy, UpdatedDate)
  SELECT 'U', 'DT.NewDetails', d.Guid, 'StatusID', d.StatusID, i.StatusID,
CASE WHEN i.ModifiedBy IS NULL THEN GETDATE() ELSE i.ModifiedBy AS ModifiedBy, 
CASE WHEN i.ModifiedDate IS NULL THEN '11111111-1111-1111-1111-111111111111' ELSE i.ModifiedDate AS ModifiedDate
FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid
WHERE      (d.StatusID IS NULL AND i.StatusID IS NOT NULL)
    OR (d.StatusID IS NOT NULL AND i.StatusID IS NULL)
    OR (d.StatusID <> i.StatusID)

У меня не было времени, чтобы убедиться, что синтаксис идеален, но если у вас есть некоторые проблемы с ним, я могу помочь.

В ответ на ваш EDIT это довольно легко сделать с помощью чего-то вроде

IF (SELECT COUNT(*) FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid) = 1
BEGIN
PRINT 'Only one update record'
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...