La sous-requête a renvoyé plus de 1 valeur – Mon triggersur ne peut pas gérer plus d'une mise à jour de ligne

J'ai un triggersur sur une table appelée StockItem , qui se triggers sur l'événement de mise à jour de ligne de table dans le MSSQL.

Le triggersur semble fonctionner, si seulement une ligne (c.-à-d. Un produit) est mise à jour.

Toutefois, lorsque plus d'une ligne est mise à jour, j'obtiens l'erreur suivante:

Msg 512, niveau 16, état 1, procédure IC_ProductUpdate, ligne 7

La sous-requête a renvoyé plus d'une valeur. Cela n'est pas autorisé lorsque la sous-requête suit =,! =, <, <=,>,> = Ou lorsque la sous-requête est utilisée comme une expression. La déclaration a été résiliée.

Voici mon triggersur:

ALTER TRIGGER [dbo].[IC_ProductUpdate] ON [dbo].[StockItem] AFTER UPDATE AS BEGIN -- Get Product Id DECLARE @StockItemID INT = (SELECT ItemID FROM INSERTED); -- Proceed If This Product Is Syncable IF (dbo.IC_CanSyncProduct(@StockItemID) = 1) BEGIN -- Check If Product Was Synced IF ((SELECT COUNT(*) FROM IC_ProductCreateQueue WHERE StockItemID = @StockItemID) > 0) BEGIN -- Check If Any Important Columns Was Updated IF (UPDATE(Weight) OR UPDATE(SpareNumber1)) 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 END ELSE BEGIN -- Insert [ProductCreate] Queue Entry INSERT INTO IC_ProductCreateQueue (StockItemID, Synced) VALUES (@StockItemID, 0); -- Insert [ProductUpdate] Queue Entry INSERT INTO IC_ProductUpdateQueue (StockItemID, Synced) VALUES (@StockItemID, 0); END END END 

Quelle est la meilleure façon de gérer les mises à jour multi-lignes dans mon triggersur?

Donc, je pense que j'ai suivi votre logique tout au long, et l'a mis en place. J'ai essayé de commenter les deux articles de façon appropriée, mais il se passe beaucoup de choses, alors n'hésitez pas à me requestr d'élaborer sur certaines sections.

La base semble être que seuls les loggings où dbo.IC_CanSyncProduct(i.ItemID) = 1 sont affectés, alors il y a 3 twigs:

  1. L'élément n'existe pas dans IC_ProductCreateQueue

    -> INSERT dans IC_ProductCreateQueue et IC_ProductUpdateQueue

  2. Les champs keys ont été mis à jour et l'élément existe dans IC_ProductCreateQueue et IC_ProductUpdateQueue

    -> UPDATE IC_ProductUpdateQueue

  3. Les champs keys ont été mis à jour et l'élément existe dans IC_ProductCreateQueue mais pas dans IC_ProductUpdateQueue

    -> INSERT IC_ProductUpdateQueue

Scénarios 2 et 3 et gérés par le MERGE ci-dessous, le scénario 1 est géré par l'instruction insert.

 ALTER TRIGGER [dbo].[IC_ProductUpdate] ON [dbo].[StockItem] AFTER UPDATE AS BEGIN -- MERGE ITEMS INTO UPDATE QUEUE WHERE KEY FIELDS WERE UPDATED -- AND PRODUCT CAN BE SYNCED AND THE ITEM EXISTS IN THE CREATE QUEUE WITH MergeData AS ( SELECT i.ItemID FROM inserted AS i INNER JOIN deleted AS d ON d.ItemID = i.ItemID WHERE dbo.IC_CanSyncProduct(i.ItemID) = 1 AND (i.SpareNumber1 != d.SpareNumber1 OR i.Weight != d.Weight) AND EXISTS ( SELECT 1 FROM IC_ProductCreateQueue AS pcq WHERE pcq.StockItemID = i.ItemID ) ) MERGE IC_ProductUpdateQueue AS puq USING MergeData AS i ON i.ItemID = puq.StockItemID WHEN MATCHED THEN UPDATE SET Synced = 1 WHEN NOT MATCHED THEN INSERT (StockItemID, Synced) VALUES (i.ItemID, 0); -- INSERT INTO BOTH THE UPDATE AND CREATE QUEUES WHERE THE ITEM -- DOES NOT ALREADY EXIST IN THE CREATE QUEUE AND THE PRODUCT -- CAN BE SYNCED INSERT IC_ProductCreateQueue (StockItemID, Synced) OUTPUT inserted.StockItemID, inserted.Synced INTO IC_ProductUpdateQueue (StockItemID, Synced) SELECT i.ItemID, 0 FROM inserted AS i WHERE dbo.IC_CanSyncProduct(i.ItemID) = 1 AND NOT EXISTS ( SELECT 1 FROM IC_ProductCreateQueue AS pcq WHERE pcq.StockItemID = i.ItemID ); END