I have two tables tblproduct and tblproductsales. I want to see how Begin Tran, Rollback work.
There is one insert statement and update statement in the stored proc. If either one of statements fail, both should rollback. but rollback is not working even if Update statement is failing. any suggestion please?
CREATE PROCEDURE spbasam_ProductSales
@ProductId int,
@QtyNeeded int
AS
BEGIN
--Check the if you have enough stock to see
DECLARE @productavailabiltycount int
SELECT @productavailabiltycount = QtyAvailable FROM dbo.tblProduct where ProductId = @ProductId
--check to see if you have enough
If (@productavailabiltycount < @QtyNeeded)
BEGIN
Raiserror('Not enough stock available',16,1)
END
Else
BEGIN
BEGIN TRY
BEGIN TRAN
--Step 1 to reduce tblProduct table
DECLARE @toupdate int
UPDATE dbo.tblProduct set QtyAvailable = @productavailabiltycount - @QtyNeeded
WHERE ProductId = @ProductId
-- Step 2 insert into tblProductSales table
--First get the max count of the productSalesId
DECLARE @maxcountid int
SELECT @maxcountid = MAX(ProductSalesId) from dbo.tblProductSales
INSERT INTO dbo.tblProductSales Values(@maxcountid+1 , @ProductId, @QtyNeeded)
COMMIT TRAN
END TRY
BEGIN CATCH
Rollback Transaction
SELECT
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_STATE() as ErrorState,
ERROR_LINE() as ErrorLine
END CATCH
END
END
Exec spbasam_ProductSales 1,10
updatestatement:if @@rowcount = 0 raiserror('Update failed.'16,1), then it would kick it to thecatchblock and won't continue to execut the remaining statements after theupdatestatement. - James L.QtyAvailableoutside the transaction and then using the (possibly stale) value within the transaction. That's a recipe for a difficult to locate race condition if another process alters the value between your operations. It's all the more fun since you don't... set QtyAvailable -= @QtyNeeded ...in theupdate. That would at least use the latest value, even if theifcondition was no longer met. - HABOidentitycolumn (@MaxCountId + 1) is generally to be avoided. And identifying the columns ininsertstatements (insert ( ProductSalesId, ProductId, QuantityStolen ) values ( @OptimisticValue, @ProductId, @QtyNeeded );) makes maintenance somewhat more predictable. (What happens if the table schema changes, e.g. a column is added between existing columns?) - HABO