10

我们有一个数据库,其中包含一个名为WarehouseItem的表,其中保存了产品的库存水平。我需要知道这个表什么时候更新,所以我创建了一个触发器来放置这个更新的表行的主键;到一个单独的表中(如队列系统)。

这是我的触发器:

IF ((SELECT COUNT(*) FROM sys.triggers WHERE name = 'IC_StockUpdate') > 0)
    DROP TRIGGER [dbo].[IC_StockUpdate]
GO
CREATE TRIGGER [dbo].[IC_StockUpdate] ON [dbo].[WarehouseItem]
AFTER UPDATE
AS
BEGIN

    -- Get Product Id
    DECLARE @StockItemID INT = (SELECT ItemID FROM INSERTED);
    DECLARE @WarehouseID INT = (SELECT WarehouseID FROM INSERTED);

    -- Proceed If This Product Is Syncable
    IF (dbo.IC_CanSyncProduct(@StockItemID) = 1)
    BEGIN

        -- Proceed If This Warehouse Is Syncable
        IF (dbo.IC_CanSyncStock(@WarehouseID) = 1)
        BEGIN

            -- Check If Product Is Synced
            IF ((SELECT COUNT(*) FROM IC_ProductCreateQueue WHERE StockItemID = @StockItemID) > 0)
            BEGIN

                -- Check If Stock Update Queue Entry Already Exists
                IF ((SELECT COUNT(*) FROM IC_StockUpdateQueue WHERE StockItemID = @StockItemID) > 0)
                BEGIN

                    -- Reset [StockUpdate] Queue Entry
                    UPDATE IC_StockUpdateQueue SET Synced = 0
                    WHERE StockItemID = @StockItemID;

                END
                ELSE
                BEGIN

                    -- Insert [StockUpdate] Queue Entry
                    INSERT INTO IC_StockUpdateQueue (StockItemID, Synced) VALUES
                    (@StockItemID, 0);

                END

            END
            ELSE
            BEGIN

                -- Insert [ProductCreate] Queue Entry
                INSERT INTO IC_ProductCreateQueue (StockItemID, Synced) VALUES
                (@StockItemID, 0);

                -- Insert [StockUpdate] Queue Entry
                INSERT INTO IC_StockUpdateQueue (StockItemID, Synced) VALUES
                (@StockItemID, 0);

            END

        END

    END

END
GO

如果在“WarehouseItem”表中只更新了一行,这将非常有效。但是,如果此表中更新了不止一行,我的触发器将无法处理它:

在此处输入图像描述

有没有办法在大规模更新事件后迭代“插入”集合?或者如何处理触发器中的多行更新?

4

3 回答 3

3

你用这个:

-- Get Product Id
DECLARE @StockItemID INT = (SELECT ItemID FROM INSERTED);
DECLARE @WarehouseID INT = (SELECT WarehouseID FROM INSERTED);

但是,如果您更新多行(作为您的示例),则必须使用不同的策略。

例如,要声明一个变量,请在查询中使用 INSERTED 表在 JOIN 中现在您使用变量的位置。

IF 语句适用于您的变量,但我认为在查询中移动该条件。

尝试以这种方式更改您的 UPDATE 查询(最终添加 IF 条件):

-- Reset [StockUpdate] Queue Entry
UPDATE IC_StockUpdateQueue SET Synced = 0
FROM inserted 
WHERE inserted.itemID = StockItemID;

等等。

如需更多信息,请添加评论。

于 2013-09-09T10:28:26.277 回答
2

您可以使用循环进行迭代,INSERTED但最好将标量变量更改为 aTABLE以及ID 满足前两个 IF 标准的INSERT-SELECT位置INSERTED

DECLARE @inserted TABLE (StockItemID INT, WarehouseID INT)

INSERT INTO @inserted (StockItemID, WarehouseID)
SELECT StockItemID, WarehouseID
FROM INSERTED i
WHERE dbo.IC_CanSyncProduct(i.StockItemID)=1
AND dbo.IC_CanSyncStock(i.WarehouseID)=1

然后您可以删除 if else upsert 逻辑并使用进一步过滤@inserted所需的各种更新和插入的查询

;WITH ResetQueueEntry
(
    SELECT StockItemID
    FROM @inserted i
    WHERE EXISTS(SELECT 1 FROM IC_ProductCreateQueue q WHERE q.StockItemID = i.StockItemID)
    AND EXISTS(SELECT 1 FROM IC_StockUpdateQueue q WHERE q.StockItemID = i.StockItemID))
)

-- Reset [StockUpdate] Queue Entry
UPDATE IC_StockUpdateQueue 
SET Synced = 0
WHERE StockItemID IN (SELECT StockItemID FROM ResetStockUpdate);

WITH InsertQueueEntry
(
     SELECT StockItemId, 0 Synced
     FROM @inserted
     WHERE EXISTS(SELECT 1 FROM IC_ProductCreateQueue q WHERE q.StockItemID = i.StockItemID)       
     AND NOT EXISTS(SELECT 1 FROM IC_StockUpdateQueue q WHERE q.StockItemID = i.StockItemID))
)
-- Insert [StockUpdate] Queue Entry
INSERT INTO IC_StockUpdateQueue (StockItemID, Synced)
SELECT StockItemID, Synced
FROM InsertQueueEntry

WITH CreateProductEntry
(
     SELECT StockItemId, 0 Synced
     FROM @inserted
     WHERE NOT EXISTS(SELECT 1 FROM IC_ProductCreateQueue q WHERE q.StockItemID = i.StockItemID)
)
-- Insert [ProductCreate] Queue Entry
INSERT INTO IC_ProductCreateQueue (StockItemID, Synced)
SELECT StockItemId, Synced
FROM CreateProductEntry

WITH CreateStockEntry
(
     SELECT StockItemId, 0 Synced
     FROM @inserted
     WHERE NOT EXISTS(SELECT 1 FROM IC_ProductCreateQueue q WHERE q.StockItemID = i.StockItemID)
)
-- Insert [StockUpdate] Queue Entry
INSERT INTO IC_StockUpdateQueue (StockItemID, Synced)
SELECT StockItemId, Synced
FROM CreateProductEntry
于 2013-09-09T10:51:35.543 回答
1

如果触发器用于 INSERT,UPDATE 此代码将退出触发器 IF 记录正在更新并且多个记录受到影响:

IF (SELECT COUNT(*) FROM Deleted) > 1
  BEGIN
     Return
  END

但是,如果您希望检查 INSERTED 记录集中的每条记录,您可以使用以下方法:

   DECLARE rstAST CURSOR FOR
   SELECT ins.TaskActionId,
          _Task.CustomerId,
          _AST.ASTQRId,
          ins.ExistingQRcode,
          ins.NewQRcode
          FROM Inserted ins INNER JOIN
               dbo.cdn_AST _AST ON ins.ASTId = _AST.ASTId INNER JOIN
               dbo.tsk_Task _Task ON ins.TaskId = _Task.TaskId

    OPEN rstAST
    FETCH NEXT FROM rstAST INTO @TaskActionId, @TaskCustomerId, @ASTQRId, @ExistingQRcode, @NewQRcode
    WHILE @@FETCH_STATUS = 0
    BEGIN
      --use CONTINUE to skip next record or let it traverse the loop

      FETCH NEXT FROM rstAST INTO @TaskActionId, @TaskCustomerId, @ASTQRId, @ExistingQRcode, @NewQRcode
    END
    CLOSE rstAST
    DEALLOCATE rstAST
于 2018-12-04T16:26:54.337 回答