我正在遵循有关ACID概念的在线交易教程。我有这两个表:
-- Create Product table
CREATE TABLE Product
(
ProductId INT PRIMARY KEY,
Name VARCHAR(50),
Price INT,
Quantity INT
)
GO
-- Populate the Product Table with some test data
INSERT INTO Product VALUES(101, 'Laptop', 1234, 100)
INSERT INTO Product VALUES(102, 'Desktop', 3456, 150)
INSERT INTO Product VALUES(103, 'Tablet', 5678, 200)
INSERT INTO Product VALUES(104, 'Mobile', 7890, 250)
GO
-- Create ProductSales table
CREATE TABLE ProductSales
(
ProductSalesId INT PRIMARY KEY,
ProductId INT,
QuantitySold INT
)
GO
我通过交易创建了一个存储过程,在其中提供了productId和要出售的数量。
这是我的存储过程:
CREATE PROCEDURE spSellProduct
@ProductID INT,
@QuantityToSell INT
AS
BEGIN
-- First we need to Check the stock available for the product we want to sell
DECLARE @StockAvailable INT
SELECT @StockAvailable = Quantity
FROM Product
WHERE ProductId = @ProductId
-- We need to throw an error to the calling application
-- if the stock is less than the quantity we want to sell
IF(@StockAvailable< @QuantityToSell)
BEGIN
Raiserror('Enough Stock is not available',16,1)
END
-- If enough stock is available
ELSE
BEGIN
BEGIN TRY
-- We need to start the transaction
BEGIN TRANSACTION
-- First we need to reduce the quantity available
UPDATE Product SET
Quantity = (Quantity - @QuantityToSell)
WHERE ProductID = @ProductID
-- Calculate MAX ProductSalesId
DECLARE @MaxProductSalesId INT
SELECT @MaxProductSalesId = CASE
WHEN MAX(ProductSalesId) IS NULL THEN 0
ELSE MAX(ProductSalesId)
END
FROM ProductSales
-- Increment @MaxProductSalesId by 1, so we don't get a primary key violation
Set @MaxProductSalesId = @MaxProductSalesId + 1
-- We need to insert the quantity sold into the ProductSales table
INSERT INTO ProductSales(ProductSalesId, ProductId, QuantitySold)
VALUES(@MaxProductSalesId, @ProductId, @QuantityToSell)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_STATE() as ErrorState,
ERROR_SEVERITY() as ErrorSeverity,
ERROR_LINE() as ErrorLine
END CATCH
End
END
go
spSellProduct @ProductId=103, @QuantityToSell=300
我检查数量是否少于要出售的数量,然后产生错误。 如果没有错误,那么我开始交易。
然后从产品表中扣除数量。 之后,我在productSales表中增加ProductSalesId,并使用ProductId和QuantitySold插入新行。
如果发生任何错误,我尝试在捕获批次中处理它们并回滚事务。
因此,在我的ProductId 103的Product表中,该表有200个库存,我通过以下方式执行存储过程:
spSellProduct @ ProductId = 103,@ QuantityToSell = 300
@QuantityToSell大于“数量”时,不会生成错误并且事务不会回滚。在这种情况下,ProductId的数量为200,而我尝试出售的数量为300。
我在做什么错了?
谢谢
答案 0 :(得分:0)
您应该将所有过程代码放在try catch中,并在其中放入事务。尝试使用以下代码。
CREATE PROCEDURE [dbo].[spSellProduct]
@ProductID INT,
@QuantityToSell INT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
-- First we need to Check the stock available for the product we want to sell
DECLARE @StockAvailable INT
SELECT @StockAvailable = Quantity
FROM Product
WHERE ProductId = @ProductId
-- We need to throw an error to the calling application
-- if the stock is less than the quantity we want to sell
IF(@StockAvailable< @QuantityToSell)
BEGIN
Raiserror('Enough Stock is not available',16,1)
END
-- If enough stock is available
ELSE
BEGIN
-- First we need to reduce the quantity available
UPDATE Product SET
Quantity = (Quantity - @QuantityToSell)
WHERE ProductID = @ProductID
-- Calculate MAX ProductSalesId
DECLARE @MaxProductSalesId INT
SELECT @MaxProductSalesId = CASE
WHEN MAX(ProductSalesId) IS NULL THEN 0
ELSE MAX(ProductSalesId)
END
FROM ProductSales
-- Increment @MaxProductSalesId by 1, so we don't get a primary key violation
Set @MaxProductSalesId = @MaxProductSalesId + 1
-- We need to insert the quantity sold into the ProductSales table
INSERT INTO ProductSales(ProductSalesId, ProductId, QuantitySold)
VALUES(@MaxProductSalesId, @ProductId, @QuantityToSell)
END
COMMIT TRANSACTION CHECKTR
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_STATE() as ErrorState,
ERROR_SEVERITY() as ErrorSeverity,
ERROR_LINE() as ErrorLine
END CATCH
END