2013-09-09 5 views
6

У нас есть база данных с таблицей WarehouseItem, где хранятся уровни запасов продукта. Мне нужно знать, когда эта таблица будет обновлена, поэтому я создал триггер, чтобы перенести первичный ключ этой строки таблицы, которая была обновлена; в отдельную таблицу (например, систему очереди).Обработка нескольких строк в триггере SQL Server

Это мой триггер:

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». Однако, если более чем один ряд обновляется в этой таблице, мой триггер не в состоянии справиться с этим:

enter image description here

Есть ли способ для перебора «вставленной» коллекции после события массового обновления? Или как обрабатывать несколько обновлений строк в триггере?

+0

Следуя обеспечивает хорошее объяснение Резо e проблема, https: //www.mssqltips.com/sqlservertip/2342/understanding-sql-server-inserted-and-deleted-tables-for-dml-triggers/ Я использовал следующие условия для захвата вставки, удаления и обновления SELECT @ DELCOUNT = COUNT (*) FROM DELETED \t SELECT @ INSCOUNT = COUNT (*) FROM INSERTED IF @ DELCOUNT = 0 - INSERT, ELSE IF @INSCOUNT = 0 - DELETE и т. Д. – Buminda

ответ

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; 

И так далее.

Для получения дополнительной информации, добавьте комментарий.

+0

Я думаю, что я понимаю, куда вы идете от этого. Спасибо за этот совет. Я думаю, что это то, что мне нужно. – Latheesan

+1

@LatheesanKanes: Хорошо, если вы хотите, я здесь;) –

+0

Это не работает для меня, я попытался присоединиться к таблице INSERTED, но он все равно дает мне ту же ошибку, то есть подзапрос возвращает более одной строки. Я пытаюсь обновить несколько строк в одном запросе, используя инструкцию типа «UPDATE Table1 SET col1 = col1», можете ли вы мне помочь в этом. –

2

Вы можете использовать цикл для перебора INSERTED, но это может быть лучше изменить переменные скалярные в TABLE и 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 

тогда вам можно удалить, если еще 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