Comment faire un T-SQL Curseur plus rapidement?

Hey, j'Ai un curseur dans une procédure stockée sous SQL Server 2000 (pas possible de mettre à jour maintenant) que toutes les mises à jour de la table, mais il prend généralement que quelques minutes à remplir. J'ai besoin pour le rendre plus rapide. Ici l'exemple du tableau filtré par l'arbitraire d'un id de produit;
Exemple de table http://img231.imageshack.us/img231/9464/75187992.jpg
Alors que GDEPO d'Entrée:dépôt, CDEPO:Sortie de depot,d'Adet: quantité,E_CIKAN quantité utilisée.

Enregistrement explications:
1: 20 unité entre depot 01,
2: unité de 10 feuilles de 01.
3: 5 Unité de feuilles 01 (E_CIKAN pour le 1er record de 15 maintenant)
4: 10 plus d'unité entre depot 01.
5: 3 de l'unité de feuilles de 01 à partir du 1er enregistrement. Notez maintenant le 1er enregistrement a E_CIKAN fixé à 18 ans.
6: C'est là que le problème vient de: 3 unité doit quitter depot 01. Il faut que les 2 unité à partir du 1er enregistrement et de 1 unité à partir de la 5ème record. Ma SP peut gérer cette amende comme on le voit dans l'image, sauf que c'est VRAIMENT lent.

Voici la procédure stockée traduits en anglais;

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],QTY,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, @SK,@DEMAND,@DP
END
CLOSE SH
DEALLOCATE SH
Vos requêtes sont à l'aide d'un tas de colonnes qui ne sont pas répertoriés dans votre capture d'écran. Il serait probablement mieux si vous avez inclus le DDL pour la table avec de véritables descriptions des colonnes.
Tom, j'ai traduit la requête en anglais et dit Whereas GDEPO:Entry depot, CDEPO:Exit depot,Adet: quantity,E_CIKAN quantity that's used. après la capture d'écran.
E_CIKAN indique la quantité utilisée (par les documents ci-après) de la quantité. Vérifier d'abord les enregistrements de 3, 20 entrée,10+5 de départ. E_CIKAN pour le 1er record de 15. Une procédure stockée est-ce que cela amende, le problème est qu'il est vraiment lent.
(toutes mes excuses, j'ai été la suppression de mes commentaires que je comprends de plus). OK, je comprends maintenant. Donc E_CIKAN montre comment de nombreux de la ADET ont été utilisés. Donc, il commence à 0 et de votre procédure stockée ajoute à elle. Par conséquent, votre capture d'écran montre les valeurs finales après la procédure.
Vous n'avez pas besoin d'un curseur imbriqué ou même n'importe quel curseur pour faire ce que vous essayez de faire, vous pouvez écrire un peu de mise à jour des déclarations ou si c'est vraiment complexe de l'utilisation d'une table temporaire pour obtenir un calcul, puis faire votre mise à jour. Mais rien de logique-sage dans vos curseurs nécessitent l'utilisation de curseurs.

OriginalL'auteur Ertugrul Kara | 2009-05-13