如何使T-SQL游标更快?

前端之家收集整理的这篇文章主要介绍了如何使T-SQL游标更快?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
嘿,我在sql Server 2000下的存储过程中有一个游标(现在无法更新),它会更新所有表,但通常需要几分钟才能完成.我需要让它更快.这是由任意产品ID过滤的示例表;
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以匹配,显然)

这意味着你的外部游标将循环通过更少的行,并且你的内部游标将具有相同数量的行来循环.

所以这应该更快.

猜你在找的MsSQL相关文章