I have a pending order table with a check constraint to prevent people from ordering an item we don’t have in stock. This required me to create a counter function to decide if an insert can happen or not. It works until there is 1 item left in inventory then I get a message that we are out of stock of the item. I thought it was a dirty read issue but even after interducing a ReadPast hint I still see this behavior. Is there some other factor causing this problem? Or do I need to setup the isolation level differently?
I have tried calling this function with the sprokID and it returns true which is why I am thinking during insert there is a dirty read taking place.
ALTER TABLE [dbo].[PendingSprokOrders] WITH CHECK ADD CONSTRAINT [CK_SprokInStock] CHECK (([dbo].[SprokInStockCount]([SprokID])=(1)))
FUNCTION [dbo].[SprokInStockCount] ( @SprokId INT )
RETURNS INT
AS
BEGIN
DECLARE @Active INT
SET @Active = ( SELECT COUNT(*)
FROM [PendingSprokOrders] AS uac WITH(READPAST)
WHERE uac.SprokID = @SprokId
)
DECLARE @Total INT
SET @Total = ( SELECT
ISNULL(InStock, 0)
FROM SprokInvetory
WHERE id = @SprokId
)
DECLARE @Result INT
IF @Total - @Active > 0
SET @Result = 1
ELSE
SET @Result = 0
RETURN @Result;
END;
The math is off. Instead of:
it should be:
That’s because your constraint function can see the row that you are attempting to add and is counting it.