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

在处理多个插入/更新的记录时使用IF-UPDATE-on-SQL触发器,sql,sql-server,triggers,Sql,Sql Server,Triggers,我使用此SQL Server触发器从特定表中查找多条记录的插入/更新,并将其放入另一个队列表中以供稍后处理 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

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

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 UPDATEcolX?

您可以加入到deleted并使用where i.Name D.Name


你可以加入到已删除并使用where I.Name D.Name


首先,我建议每个操作有一个单独的触发器——一个用于插入,另一个用于更新。保持代码的整洁,减少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
更新触发器需要进行一次额外的检查,以查看两列中的一列是否已更改。通过将插入的伪表与更新后的新值相结合,以及将删除的伪表与更新前的旧值相结合,可以非常轻松地处理此问题:


首先,我建议每个操作有一个单独的触发器——一个用于插入,另一个用于更新。保持代码的整洁,减少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
更新触发器需要进行一次额外的检查,以查看两列中的一列是否已更改。通过将插入的伪表与更新后的新值相结合,以及将删除的伪表与更新前的旧值相结合,可以非常轻松地处理此问题:


可能的重复可能的重复这正是我在寻找和感谢的信息。为了其他人的利益,我想补充一点,加入到已删除的表示更新之前的旧值,并且没有记录被实际删除。这正是我所寻找的,非常感谢这些信息。为了其他人的缘故,我想补充一点,join to deleted表示更新之前的旧值,并且实际上没有删除任何记录。
ALTER TRIGGER [dbo].[IC_ProductUpdate] ON [dbo].[StockItem]
AFTER UPDATE
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
    INNER JOIN Deleted d ON d.StockItemID = i.StockItemID
    WHERE
        i.Name <> d.Name OR i.Description <> d.Description

    -- 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
        INNER JOIN 
            Deleted d ON d.StockItemID = i.StockItemID
        WHERE 
            i.Name <> d.Name OR i.Description <> d.Description
            AND NOT EXISTS (SELECT * FROM dbo.IC_ProductUpdateQueue puq
                            WHERE puq.StockItemID = i.StockItemID)
END