在操作相关行的值时,SQL替代Cursor

时间:2011-07-14 11:01:15

标签: sql-server cursor

我有一个存储库存水平的简单表格。即

ID int PK
LocationID int
StockLevel real

此表中每个位置可能有多行,即:

ID | LocationID | StockLevel
----------------------------
1  |      1     | 100
2  |      1     | 124
3  |      2     | 300

在这个例子中,看到224个单位存在于位置1是微不足道的。

当我减少我在使用的位置1的库存水平时 一个游标迭代在LocationID为1的所有行并使用一些简单的行 逻辑决定当前行可用的股票是否满足传入的要求 减少价值。如果行有足够的数量来满足要求我减少行值并退出游标,并结束过程,但是如果行没有足够的可用数量,我将其值减少为零并移动到下一行并尝试再次(减少数量)

它非常简单并且工作正常,但不可避免的问题是:有没有一种表现方式 没有游标的这个RBAR操作?我试图寻找替代品,甚至是措辞 这种操作的搜索标准很痛苦!

提前致谢 尼克

PS。我以这种格式存储数据,因为每一行还包含其他唯一的列,因此不能简单地将每个列聚合成一行。

PPS。请求光标逻辑(其中'@DecrementStockQuantityBy'是我们需要的数量 在指定地点减少库存水平):

WHILE @@FETCH_STATUS = 0
BEGIN

   IF CurrentRowStockStockLevel >= @DecrementStockQuantityBy
   BEGIN

          --This row has enough stock to satisfy decrement request
        --Update Quantity on the Current Row by @DecrementStockQuantityBy   
          --End Procedure       
          BREAK

   END

   IF CurrentRowStockStockLevel < @DecrementStockQuantityBy
   BEGIN

         --Update CurrentRowStockStockLevel to Zero
         --Reduce @DecrementStockQuantityBy by CurrentRowStockStockLevel
         --Repeat until @DecrementStockQuantityBy is zero or end of rows reached

   END

   FETCH NEXT FROM Cursor

END

希望这个足够清楚?如果需要进一步/更好的解释,请告诉我。 感谢

1 个答案:

答案 0 :(得分:0)

你是正确的先生,一个简单的更新声明可以帮助你在这种情况下我仍然试图找到一个合法的游标使用或我无法解决CTE或基于设置。

在深入了解您的问题之后,我还将提出另一种解决方案:

Declare @LocationValue int = 1,@decimentvalue int = 20


with temp (id,StockLevel,remaining) as (
select top 1 id, Case when StockLevel - @decimentvalue >0 then
           StockLevel = StockLevel - @decimentvalue 
         else 
           StockLevel = 0
         end,  @decimentvalue - StockLevel
from simpleTable st
where st.LocationID  = @LocationValue
union all 
select top 1 id, Case when StockLevel - t.remaining >0 then
           StockLevel = StockLevel -t.remaining 
         else 
           StockLevel = 0
         end,  t.remaining - StockLevel
from simpleTable st
where st.LocationID  = @LocationValue
and exists (select remaining from temp t
            where st.id <> t.id
            group by t.id
            having min(remaining ) >0) )

update st
set st.StockLevel = t.StockLevel
from simpleTable st
inner join temp t on t.id = st.id