嘿,我在sql Server 2000下的存储过程中有一个游标(现在无法更新),它会更新所有表,但通常需要几分钟才能完成.我需要让它更快.这是由任意产品ID过滤的示例表;
Example table http://img231.imageshack.us/img231/9464/75187992.jpg
而GDEPO:入境仓库,CDEPO:退出仓库,Adet:数量,E_CIKAN使用的数量.
Example table http://img231.imageshack.us/img231/9464/75187992.jpg
而GDEPO:入境仓库,CDEPO:退出仓库,Adet:数量,E_CIKAN使用的数量.
记录解释:
1:20单位进入仓库01,
2:10单位离开01.
3:5单位离开01(第一记录的E_CIKAN现在为15)
4:10更多单位进入仓库01.
5:3单位从第1记录离开01.现在注意第一条记录的E_CIKAN设置为18.
6:这就是问题所在:3个单位需要离开仓库01.从第1个记录需要2个单位,从第5个记录需要1个单位.我的SP可以处理这个如图所示的罚款,除非它真的很慢.
这是存储过程翻译成英文;
CREATE PROC [dbo].[UpdateProductDetails] as UPDATE PRODUCTDETAILS SET E_CIKAN=0; DECLARE @ID int DECLARE @SK varchar(50),@DP varchar(50) --SK = STOKKODU = PRODUCTID,DP = DEPOT DECLARE @DEMAND float --Demand=Quantity,We'll decrease it record by record DECLARE @SUBID int DECLARE @SUBQTY float,@SUBCK float,@REMAINS float DECLARE SH CURSOR FAST_FORWARD FOR SELECT [ID],PRODUCTID,QTY,EXITDEPOT FROM PRODUCTDETAILS WHERE (EXITDEPOT IS NOT NULL) ORDER BY [DATE] ASC OPEN SH FETCH NEXT FROM SH INTO @ID,@SK,@DEMAND,@DP WHILE (@@FETCH_STATUS = 0) BEGIN DECLARE SA CURSOR FAST_FORWARD FOR SELECT [ID],E_CIKAN FROM PRODUCTDETAILS WHERE (QTY>E_CIKAN) AND (PRODUCTID=@SK) AND (ENTRYDEPOT=@DP) ORDER BY [DATE] ASC OPEN SA FETCH NEXT FROM SA INTO @SUBID,@SUBQTY,@SUBCK WHILE (@@FETCH_STATUS = 0) AND (@DEMAND>0) BEGIN SET @REMAINS=@SUBQTY-@SUBCK IF @DEMAND>@REMAINS --current record isnt sufficient,use it and move on BEGIN UPDATE PRODUCTDETAILS SET E_CIKAN=QTY WHERE ID=@SUBID; SET @DEMAND=@DEMAND-@REMAINS END ELSE BEGIN UPDATE PRODUCTDETAILS SET E_CIKAN=E_CIKAN+@DEMAND WHERE ID=@SUBID; SET @DEMAND=0 END FETCH NEXT FROM SA INTO @SUBID,@SUBAD,@SUBCK END CLOSE SA DEALLOCATE SA FETCH NEXT FROM SH INTO @ID,@DP END CLOSE SH DEALLOCATE SH
解决方法
根据我在这个问题的其他答案中的对话,我想我已经找到了加快日常工作的方法.
你有两个嵌套游标:
>第一个是选择指定了exitdepot的每一行.它需要产品,depo和数量,然后:
>内部游标循环遍历指定了entrydepot的产品/库的行.它为每一个添加了E_CIKAN,直到它分配了所有产品.
因此,对于您拥有的每个exitdepot行,内部游标循环至少运行一次.但是,您的系统并不真正关心哪些项目与哪个事务发生了关系 – 您只是想计算最终的E_CIKAN值.
所以……
您的外部循环只需要获得每个产品/仓库组合的运出物品总量.因此,您可以将外部游标定义更改为:
DECLARE SH CURSOR FAST_FORWARD FOR SELECT PRODUCTID,EXITDEPOT,Sum(Qty) as TOTALQTY FROM PRODUCTDETAILS WHERE (EXITDEPOT IS NOT NULL) GROUP BY PRODUCTID,EXITDEPOT OPEN SH FETCH NEXT FROM SH INTO @SK,@DP,@DEMAND
(然后还要在代码末尾从SH更改匹配的FETCH以匹配,显然)
这意味着你的外部游标将循环通过更少的行,并且你的内部游标将具有相同数量的行来循环.
所以这应该更快.