使用变量时更新时的奇怪更新行为

时间:2012-11-21 00:11:00

标签: sql sql-server sql-server-2008-r2 sql-update

这是我的问题Reference a column and update it in the same statement的后续内容。我现在正在尝试使用局部变量并在同一更新语句中更新它。

declare @tmp table (ID int primary key, UNPAID money)

insert into @tmp select 1, 31.63
insert into @tmp select 2, 49.20
insert into @tmp select 3, 99.00
insert into @tmp select 4, 41.00

declare @paymentAmmount money
select @paymentAmmount = SUM(UNPAID) from @tmp

declare cur_oustandingAR cursor local static for select ID  from @tmp order by ID
open cur_oustandingAR

declare @currentID int

fetch next from cur_oustandingAR into @currentID
while (@@fetch_status = 0 and @paymentAmmount > 0)
begin
    begin
        update @tmp
            set UNPAID = case when @paymentAmmount > UNPAID then 0 else UNPAID - @paymentAmmount end,
                @paymentAmmount = case when @paymentAmmount > UNPAID then @paymentAmmount - UNPAID else 0 end
            where ID = @currentID
    end
    fetch next from cur_oustandingAR into @currentID
end

select * from @tmp
select @paymentAmmount as LeftoverPayment

您可以运行查询here,这是它提供的结果

ID          UNPAID
----------- ---------------------
1           0.00
2           0.00
3           58.00
4           41.00

LeftoverPayment 
--------------- 
0               

所有的值都应为0,最后的@paymentAmmount也应该为0.导致值无法正确应用会出现什么问题?


P.S。我知道如何fix it,只是将一个查询分解为以下3个查询,但我想将其作为单个查询进行,因此我不需要对真实表进行尽可能多的查询

select @oldUnpaid = UNPAID from @tmp where ID = @currentID
update @tmp 
    set UNPAID = case when @paymentAmmount > UNPAID then 0 else UNPAID - @paymentAmmount end
    where ID = @currentID
select @paymentAmmount = case when @paymentAmmount > @oldUnpaid then @paymentAmmount - @oldUnpaid else 0 end

我只是想知道为什么我现在所做的事情不起作用。

1 个答案:

答案 0 :(得分:1)

declare @tmp table (ID int primary key, UNPAID money)

insert into @tmp select 1, 31.63
insert into @tmp select 2, 49.20
insert into @tmp select 3, 99.00
insert into @tmp select 4, 41.00

declare @paymentAmmount money
declare @paymentAmmountbuf money
select @paymentAmmount = SUM(UNPAID) from @tmp
declare cur_oustandingAR cursor local static for select ID  from @tmp order by ID
open cur_oustandingAR

declare @currentID int

fetch next from cur_oustandingAR into @currentID
while (@@fetch_status = 0 and @paymentAmmount > 0)
begin
    begin
        select @paymentAmmountbuf=@paymentAmmount

        update @tmp
            set UNPAID = case when @paymentAmmountbuf > UNPAID then 0 else UNPAID - @paymentAmmountbuf end,
                @paymentAmmount = case when @paymentAmmount > UNPAID then @paymentAmmount - UNPAID else 0 end
            where ID = @currentID
    end
    fetch next from cur_oustandingAR into @currentID
end

select * from @tmp
select @paymentAmmount as LeftoverPayment