我正在尝试更新游标内的一行。我要做的是用OLD_QTY和NEW_QTY更新记录链。但是,当我尝试进行更新时,即使我在我的declration中包含The cursor is READ ONLY
,也会出现错误for update of OLD_QTY, NEW_QTY
。如果我在select语句中包含OLD_QTY
和NEW_QTY
,则没有任何区别。
declare @current_inv_guid uniqueidentifier
declare @last_inv_guid uniqueidentifier
declare @current_vid int
declare @last_vid int
--declare @current_new_qty money
declare @last_new_qty money
--declare @current_old_qty money
declare iaCursor cursor
for select INV_GUID, old_VID
--, OLD_QTY, NEW_QTY
from #IA
order by INV_GUID, old_vid, ENTRY_NUM
for update --of OLD_QTY, NEW_QTY
open iaCursor
Fetch next from iaCursor into @current_inv_guid, @current_vid --, @current_old_qty, @current_new_qty
while @@fetch_status = 0
begin
--test to see if we hit a new chain.
if(@last_inv_guid <> @current_inv_guid or @current_vid <> @last_vid)
begin
set @last_new_QTY = (select #lots.QTY_RECEIVED from #lots where #lots.INV_GUID = @current_inv_guid and LOT_VID = @current_vid)
set @last_inv_guid = @current_inv_guid
set @last_vid = @current_vid
end
--update the current link in the chain
update #ia
set OLD_QTY = @last_new_QTY,
NEW_QTY = @last_new_QTY + QTY_CHANGE,
@last_new_QTY = @last_new_QTY + QTY_CHANGE
where current of iaCursor
--get the next link
fetch next from iaCursor into @current_inv_guid, @current_vid --, @current_old_qty, @current_new_qty
end
close iaCursor
deallocate iaCursor
答案 0 :(得分:7)
在order by
中放置select
使光标只读。
答案 1 :(得分:7)
您没有明确说明您想要的行为,因此,default rules适用,根据这些行为,游标可能是可更新的,也可能不是可更新的,具体取决于基础查询。
在可更新的游标中使用order by
是完全可以的,但是你必须更详细,并告诉SQL Server你想要的细节,例如:
declare iaCursor cursor
local
forward_only
keyset
scroll_locks
for
select INV_GUID, old_VID
from #IA
order by INV_GUID, old_vid, ENTRY_NUM
for update of OLD_QTY, NEW_QTY
答案 2 :(得分:4)
答案 3 :(得分:2)
除了你在答案中提到的原因之外,你正在做的事情与SQL的使用方式背道而驰。尝试更新集合中的数据,而不是按行更新。
我不是肯定,因为我不知道你的桌面设计,但我相信以下内容应该有效。您可以 获得更好的性能。特别是,我假设QTY_CHANGE
来自#ia
,尽管情况可能并非如此。
<击> 撞击>
<击>UPDATE #ia as a set (OLD_QTY, NEW_QTY) = (SELECT #lots.QTY_RECEIVED + (COUNT(b.*) * a.QTY_CHANGE),
#lots.QTY_RECEIVED + ((COUNT(b.*) + 1) * a.QTY_CHANGE)
FROM #lots
LEFT JOIN #ia as b
ON b.INV_GUID = a.INV_GUID
AND b.OLD_VID = a.OLD_VID
AND b.ENTRY_NUM < a.ENTRY_NUM
WHERE #lots.INV_GUID = a.INV_GUID
AND #lots.LOT_VID = a.OLD_VID)
WHERE EXISTS (SELECT '1'
FROM #lots
WHERE #lots.INV_GUID = a.INV_GUID
AND #lots.LOT_VID = a.OLD_VID)
击> <击> 撞击>
...答案的先前版本是用DB2透视图编写的,尽管它本身与数据库无关。它也存在每行使用QTY_CHANGE
的相同值的问题,这是不太可能的。这应该是一个更惯用的SQL Server 2008版本,并且更有可能输出正确的答案:
WITH RT AS (SELECT #IA.inv_guid, #IA.old_vid, #IA.entry_num,
COALESCE(MAX(#Lots.qty_received), 0) +
SUM(#IA.qty_change) OVER(PARTITION BY #IA.inv_guid, #IA.old_vid
ORDER BY #IA.entry_num)
AS running_total
FROM #IA
LEFT JOIN #Lots
ON #Lots.inv_guid = #IA.inv_guid
AND #Lots.lot_vid = #IA.old_vid)
UPDATE #IA
SET #IA.old_qty = RT.running_total - #IA.qty_change, #IA.new_qty = RT.running_total
FROM #IA
JOIN RT
ON RT.inv_guid = #IA.inv_guid
AND RT.old_vid = #IA.old_vid
AND RT.entry_num = #IA.entry_num
答案 4 :(得分:0)
某些游标声明不允许更新。 documentation在以下注释中给出了提示:
- 如果SELECT语句不支持更新(权限不足,访问不支持更新的远程表,和 所以),光标是READ_ONLY。
我试图加入&#34;插入&#34;时遇到了同样的问题。游标声明的select语句中的触发器的对象。
答案 5 :(得分:0)
使用documentation中的DYNAMIC
子句。
定义一个游标,该游标反映在滚动游标时对其结果集中的行所做的所有数据更改。每次获取时,行的数据值,顺序和成员资格都会发生变化。