問題描述
據(jù)我所知,使用 dynamic
游標將反映對基表所做的任何更改.為什么在下面的例子中沒有出現(xiàn)這種情況?
It is my understanding that with a cursor that is dynamic
will reflect any changes that are made to the base tables. Why doesn't that occur in the following example ?
我用一個表變量和一個具有相同結果的實際表嘗試了這個.如果 @@fetch_status
循環(huán)開始后的那行沒有被注釋,我會得到我期望的結果.
I tried this with a table variable and an actual table with the same results.
If the line after the beginning of the @@fetch_status
loop is uncommented I get the results I expect.
declare @BalanceTable table
(
LineId int not null identity(1, 1),
Qty int not null,
Price money not null
)
insert into @BalanceTable (Qty, Price) values (3000, 1)
insert into @BalanceTable (Qty, Price) values (40, 2)
insert into @BalanceTable (Qty, Price) values (1, 1)
insert into @BalanceTable (Qty, Price) values (2000, 1)
insert into @BalanceTable (Qty, Price) values (4047, 2)
insert into @BalanceTable (Qty, Price) values (-3000, 1)
insert into @BalanceTable (Qty, Price) values (-38, 2)
insert into @BalanceTable (Qty, Price) values (3000, 1)
declare BalanceTable cursor
dynamic for
select LineId, Qty, Price
from @BalanceTable
order by LineId
declare @LineId int
declare @Qty int
declare @Price money
open BalanceTable
fetch next from BalanceTable into @LineId, @Qty, @Price
while @@fetch_status = 0
begin
-- select @Qty = Qty, @Price = Price from @BalanceTable where LineId = @LineId
declare @SearchLessZero bit
set @SearchLessZero = case when @Qty > 0 then 1 else 0 end
declare @OffsetLineId int
declare @OffsetQty int
set @OffsetLineId = -1
while @Qty > 0 and @OffsetLineId is not null
begin
select @OffsetLineId = min(LineId)
from @BalanceTable
where LineId > @LineId and Price = @Price and
((@SearchLessZero = 1 and Qty < 0) or (@SearchLessZero = 0 and Qty > 0))
if @OffsetLineId is not null
begin
select @OffsetQty = Qty
from @BalanceTable
where LineId = @OffsetLineId
if @Qty > -@OffsetQty
begin
set @Qty = @Qty + @OffsetQty
set @OffsetQty = 0
end
else
begin
set @OffsetQty = @OffsetQty + @Qty
set @Qty = 0
end
update @BalanceTable set Qty = @OffsetQty where LineId = @OffsetLineId
end
end
update @BalanceTable set Qty = @Qty where LineId = @LineId
fetch next from BalanceTable into @LineId, @Qty, @Price
end
close BalanceTable
deallocate BalanceTable
select *
from @BalanceTable
order by LineId
推薦答案
在動態(tài)游標中只允許很少的執(zhí)行計劃運算符.如果游標查詢的執(zhí)行計劃包含不允許的操作符,游標將轉換為快照游標,因此不會看到更新.
Only very few execution plan operators are permitted in a dynamic cursor. If the execution plan for the cursor query contains a non-permitted operator, the cursor gets converted into a snapshot cursor and hence does not see updates.
如果您查看游標的執(zhí)行計劃,您會發(fā)現(xiàn)就是這樣:
if you look at the execution plan for your cursor you see that just that happened:
查詢中的問題運算符是排序.刪除它,您將看到更新.
The problem operator in your query is the sort. Remove it and you will see updates.
如果需要對數(shù)據(jù)進行排序,在表中添加聚集索引,這樣ORDER BY
就不需要排序運算符了.
If you need the data sorted, add a clustered index to the table, so that the ORDER BY
does not require a sort operator.
這篇關于動態(tài)游標不反映對基表的更新的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!