触发多行

时间:2011-04-12 16:45:38

标签: sql-server triggers rows

我已经写了一个触发器来记录对表的更改,我当然没有意识到,直到那之后,它一次只能在一条记录上运行。现在我正在尝试更新它以允许批量更新,我无法弄清楚如何执行此操作。

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 个答案:

答案 0 :(得分:2)

我相信您的条件检查可以最小化到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)

我没有时间确保语法完美,但如果你遇到一些问题,我可以提供帮助。

为了回应你的编辑,用

之类的东西很容易做到
IF (SELECT COUNT(*) FROM INSERTED i INNER JOIN DELETED d on i.Guid = d.Guid) = 1
BEGIN
PRINT 'Only one update record'
END