2014-07-02 56 views
2

我在表上觸發一個名爲StockItem的表,觸發MSSQL中的錶行更新事件。子查詢返回多個值 - 我的觸發器無法處理多個行更新

如果只更新一行(即一個產品),觸發器似乎可以工作。

然而,當有多個行更新,我得到以下錯誤:

Msg 512, Level 16, State 1, Procedure IC_ProductUpdate, Line 7

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. The statement has been terminated.

這裏是我的觸發器:

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 

什麼是處理多行更新的最佳方式在我的觸發器內?

回答

1

所以,我認爲我已經跟蹤了你的邏輯,並使其基於設置。我試圖對這兩部分進行適當的評論,但是有很多內容可以隨時請我詳細說明某些部分。

的基礎似乎是隻有在dbo.IC_CanSyncProduct(i.ItemID) = 1受影響的記錄,然後有3個分支:

  1. 項目不IC_ProductCreateQueue

    --> INSERT into both IC_ProductCreateQueue and IC_ProductUpdateQueue

  2. 重點領域存在的更新和項目同時存在於IC_ProductCreateQueueIC_ProductUpdateQueue

    --> UPDATE IC_ProductUpdateQueue

  3. 重點領域進行了更新和項目均存在IC_ProductCreateQueue但不是在IC_ProductUpdateQueue

    --> INSERT IC_ProductUpdateQueue

情景2和3,並通過以下MERGE管理,方案1是由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 
+0

感謝GarethD,你簡直太棒了!這個更新的觸發器完美無缺地工作。 :) !!! – Latheesan

相關問題