处理多个插入/更新的记录时,在SQL触发器上使用IF UPDATE

时间:2016-06-16 17:47:53

标签: sql sql-server triggers

我使用此SQL Server触发器查找特定表中多个记录的插入/更新,并将其放入另一个队列表中(稍后进行处理)。

Sub Alert()
    Dim i As Long
    i = 3

    While Workbooks("Issuers.xlsm").Sheets("Summary of Covered Companies").Cells(i, 5) <> ""

    With Workbooks("Issuers.xlsm")

        If .Sheets("Summary of Covered Companies").Cells(i, 5).Value = 1 Then

             MsgBox Workbooks("Issuers.xlsm").Sheets("Summary of Covered Companies").Cells(i, 3).Value & " is issuing their next financial statement tomorrow (" & _
            Workbooks("Issuers.xlsm").Sheets("Summary of Covered Companies").Cells(i, 4).Value & ")."

        End If

    End With

   i = i + 1

   Wend

End Sub

这样可以正常工作,但是如果某些列已更新,我只希望上面的触发器做出反应。

我感兴趣的专栏是:

  • 名称
  • 描述

我知道我可以使用以下T-SQL语法检查列是否真的更新(在更新事件期间),如下所示:

ALTER TRIGGER [dbo].[IC_ProductUpdate] ON [dbo].[StockItem]
AFTER INSERT, UPDATE
AS
BEGIN
    SELECT RowNum = ROW_NUMBER() OVER(ORDER BY ItemID) , ItemID
    INTO #ProductUpdates
    FROM INSERTED;

    DECLARE @MaxRownum INT;
    SET @MaxRownum = (SELECT MAX(RowNum) FROM #ProductUpdates);

    DECLARE @Iter INT;
    SET @Iter = (SELECT MIN(RowNum) FROM #ProductUpdates);

    WHILE @Iter <= @MaxRownum
    BEGIN
        -- Get Product Id
        DECLARE @StockItemID INT = (SELECT ItemID FROM #ProductUpdates WHERE RowNum = @Iter);

        -- Proceed If This Product Is Sync-able
        IF (dbo.IC_CanSyncProduct(@StockItemID) = 1)
        BEGIN
            -- Check If There Is A [ProductUpdate] Queue Entry Already Exist For This Product
            IF ((SELECT COUNT(*) FROM IC_ProductUpdateQueue WHERE StockItemID = @StockItemID) > 0)
            BEGIN
                -- Reset [ProductUpdate] Queue Entry
                UPDATE IC_ProductUpdateQueue 
                SET Synced = 0
                WHERE StockItemID = @StockItemID
            END
            ELSE
            BEGIN
                -- Insert [ProductUpdate] Queue Entry
                INSERT INTO IC_ProductUpdateQueue (StockItemID, Synced) 
                VALUES (@StockItemID, 0)
            END
        END

        SET @Iter = @Iter + 1;
    END

    DROP TABLE #ProductUpdates;
END

但是,我不确定如何将其合并到上面的触发器中,因为我的触发器同时处理多行也在更新。

有什么想法吗?触发器中的哪一点可以使用IF (UPDATE(Name) OR UPDATE(Description)) BEGIN // do something... END

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

首先,我建议为每个操作设置一个单独的触发器 - 一个用于INSERT,另一个用于UPDATE。保持代码更清晰(不那么混乱 IF 语句等等。)

INSERT触发器非常简单,因为没有什么可以检查更新 - 并且绝对不需要临时表和慢WHILE循环 - 只需要两个简单的基于集合的语句和你做完了:

CREATE TRIGGER [dbo].[IC_ProductInsert] ON [dbo].[StockItem]
AFTER INSERT
AS
BEGIN
    -- update the queue for those entries that already exist                 
    -- those rows that *DO NOT* exist yet are not being touched
    UPDATE puq
    SET Synced = 0
    FROM dbo.IC_ProductUpdateQueue puq
    INNER JOIN Inserted i ON puq.StockItemID = i.StockItemID

    -- for those rows that don't exist yet - insert the values
    INSERT INTO dbo.IC_ProductUpdateQueue (StockItemID, Synced) 
        SELECT 
            i.StockItemID, 0
        FROM
            Inserted i
        WHERE 
            NOT EXISTS (SELECT * FROM dbo.IC_ProductUpdateQueue puq
                        WHERE puq.StockItemID = i.StockItemID)
END

UPDATE触发器需要一次额外检查 - 以查看感兴趣的两列中的一列是否已更改。通过将Inserted伪表与新值(在UPDATE之后)和Deleted伪表与“旧”值组合(在{{之前),可以非常轻松地处理这个问题。 1}}):

UPDATE