I want to keep track of stock levels using AFTER UPDATE triggers in SQL Server 2019.
I have this table Units (unique items with serial numbers), table simplified for this example:
| UnitID | ProductID | SalesOrderDetailID | SerialNumber |
|---|---|---|---|
| 1 | 1 | Null | 12 |
| 2 | 1 | Null | 34 |
| 3 | 1 | Null | 56 |
| 4 | 2 | Null | 78 |
| 5 | 2 | Null | 90 |
| 6 | 2 | Null | 99 |
And this table for Stock:
| ProductID | StockSell | Updated |
|---|---|---|
| 1 | 10 | 1.1.2022 10:10:00 |
| 2 | 45 | 3.10.2022 22:48:05 |
I want to use an AFTER UPDATE trigger to update the Stock table when I assign a SalesOrderDetailID to a Unit. I managed to write the trigger for a single row update using parameters, but that's not good.
I have this at the moment:
CREATE TRIGGER tr_UnitUpdated
ON tbl1Units
AFTER UPDATE
AS
BEGIN
UPDATE tbl1Stock
SET StockSell = StockSell - 1
FROM tbl1Stock S
JOIN INSERTED I ON S.ProductID = I.ProductID
JOIN DELETED D ON I.UnitID = D.UnitID
WHERE I.SalesOrderDetailID IS NOT NULL
AND D.SalesOrderDetailID IS NULL
END
The problem is that when I assign SalesOrderDetailID to more Units in a single operation, the Stock level only reduces by 1, which after a short investigation is quite obvious because of the SET StockSell = StockSell - 1 statement.
How should I edit this statement for it to deal with bulk updates correctly?
Using the example above, if I scan units 4, 5 and 6 into a particular sales order and edit the Units table in bulk, I want the Stock Level for Product = 2 to change from 45 to 42.
Thanks in advance.
CodePudding user response:
As the updates may affect more than one ProductID, you need to GROUP BY ProductID before joining to tbl1Stock.
UPDATE S
SET StockSell = S.StockSell - I.Cnt
FROM tbl1Stock S
INNER JOIN
(
SELECT I.ProductID, Cnt = count(*)
FROM INSERTED I
WHERE I.SalesOrderDetailID IS NOT NULL
GROUP BY I.ProductID
) I ON S.ProductID = I.ProductID
Note : I didn't include the DELETED as I don't quite understand your logic on DELETED.SalesOrderDetailID IS NULL
