Handling multiple rows in SQL Server trigger

前端 未结 3 1968
一向
一向 2020-12-19 03:00

We have a database with a table called WarehouseItem where product\'s stock levels are kept. I need to know when ever this table get\'s updated, so I create

相关标签:
3条回答
  • 2020-12-19 03:44

    You could use a loop to iterate over INSERTED but it may be better to change your scalar variables into a TABLE and INSERT-SELECT from INSERTED where the IDs meet the criteria of the first two IFs

    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
    

    then you can remove the if else upsert logic and use queries that further filter @inserted for the various updates and inserts that are required

    ;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
    
    0 讨论(0)
  • 2020-12-19 03:44

    in case of the trigger is for INSERT, UPDATE this code will exit the trigger IF Records are being updated AND more than one record is being afftected:

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

    But if you wish to examin every record in the INSERTED recordset you can use this method:

       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
    
    0 讨论(0)
  • 2020-12-19 03:54

    You use this:

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

    But if you update multi rows (as your sample) you must use a different strategy.

    For example, instead to declare a variable, use INSERTED table in JOIN in query where now you use your variable.

    IF statement works on your variable but I think to move that condition in query.

    Try to change you UPDATE query in this way (eventually add condition of IF):

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

    And so on.

    For further information please add comment.

    0 讨论(0)
提交回复
热议问题