我有一个表,用于存储项目余额。
CREATE TABLE itembalance (
ItemID VARCHAR(15),
RemainingQty INT,
Cost Money,
Id INT
)
我需要确保每当发出一个项目时,都会从itembalance表中扣除适当的余额。我这样做:
DECLARE crsr CURSOR LOCAL FAST_FORWARD FOR
SELECT
itembalance.Cost,
itembalance.RemainingQty
itembalance.Id
FROM dbo.itembalance
WHERE itembalance.ItemID = @v_item_to_be_updated AND RemainingQty > 0
OPEN crsr
FETCH crsr
INTO
@cost,
@qty,
@id
WHILE @@FETCH_STATUS = 0
BEGIN
IF @qty >= @qty_to_be_deducted
BEGIN
UPDATE itembalance SET RemainingQty = RemainingQty - @qty_to_be_deducted WHERE Id = @id
/*do something with cost*/ BREAK
END
ELSE
BEGIN
UPDATE itembalance SET RemainingQty = 0 WHERE Id = @id
/*do something with cost*/ SET @qty_to_be_deducted = @qty_to_be_deducted - @qty
END
FETCH crsr
INTO
@cost,
@qty,
@id
END
CLOSE crsr
DEALLOCATE crsr
该表可能包含相同的商品代码,但成本不同。这段代码对于一次更新几个项目来说是可以的,但是每当有很多项目/数量被发送出去时,过程就会变得很慢。有没有一种方法可以优化此代码?我猜光标正在变慢,所以我想为此过程探索一个不同的代码。
答案 0 :(得分:0)
看起来您只需要一个简单的CASE
表达式:
UPDATE dbo.itembalance
SET Qty = CASE WHEN Qty >= @qty_to_be_deducted THEN Qty - @qty_to_be_deducted ELSE 0 END
WHERE ItemID = @v_item_to_be_updated
--What is the difference between Qty and RemainingQty?
--Why are you checking one and updating the other?
AND RemainingQty > 0;
答案 1 :(得分:0)
您对于该机制的要求方式和作用方式以及原因尚不清楚。
但是,假设您必须拥有多笔余额未清的记录,并且必须顺序考虑多条记录作为该机制的一部分,那么您可以通过两种方法在SQL中解决此问题(在客户端代码中进行处理是另一种选择):
1)完成操作后使用光标
2)使用临时表或表变量并对其进行迭代-与游标非常相似,但可能会更快-您必须尝试查看例如
declare @TableVariable table (Cost money, RemainingQty int, Id int, OrderBy int, Done bit default(0))
declare @Id int, @Cost money, @RemainingQty int
insert into @TableVariable (Cost, RemainingQty, Id, OrderBy)
SELECT
itembalance.Cost
, itembalance.RemainingQty
, itembalance.Id
, 1 /* Some order by condition */
FROM dbo.itembalance
WHERE itembalance.ItemID = @v_item_to_be_updated AND RemainingQty > 0
while exists (select 1 from @TableVariable where Done = 0) begin
select top 1 @Id = id, @Cost = Cost, @RemainingQty
from @TableVariable
where Done = 0
order by OrderBy
-- Do stuff here
update @TableVariable set Done = 1 where id = @Id
end
但是,您显示的代码并没有显示它应该很慢-可能是您缺少适当的索引,并且单个ItemId更新锁定了ItemBalance表中的太多行,从而影响了其他ItemId更新。