Controle de Lotes - Procedure

GALERA, QUANDO EXECUTO ESTA PROCEDURE

– Por exemplo, tenho 3 Lotes com as seguintes Quantidades

LOTE 1 - 400
LOTE 2 - 50
LOTE 3 - 50

QUANDO EXECUTO A PROC, passo por paramentro o id do produto e a quantidade.

EXEC SPAbaterLote 13, 500;

QUANDO EXECUTASSE ESTA PROCEDURE, DEVERIA SUBTRAIR, 500 - 400 = 100
E ZERAR O LOTE, DEPOIS NO PROXIMO LOTE 100 - 50 = 50, E ZERAR O LOTE,
LOGO DEPOIS 50 - 50 = 0 E ZERAR O 3 LOTE.

MAS A PROC SO ESTA SUBTRAINDO O 400 E ZERANDO E O 50 E ZERANDO, E NÃO SUBTRAI O PROXIMO LOTE.

  
   ALTER PROCEDURE [dbo].[SPAbaterLote]
(
    @IDPRODUTO INT,
    @QTD DECIMAL(15,2)
)
AS
BEGIN

   
                 DECLARE @ID_ENTRADA INT;
                 DECLARE @QUANTIDADE DECIMAL(15,2);
                 DECLARE @DATAPROX DATETIME;
                 DECLARE @VALORTOTAL DECIMAL(15,2);
                 DECLARE @ID_LOTE INT;
   

         -- Seleciono o id da entrada do lote mais antigo
         SET @ID_ENTRADA = (SELECT TOP 1 tbE.ID_ENTRADA
                                   FROM tb_Entradas as tbE
                                   WHERE tbE.DATA_ENTRADA = (SELECT MIN(tbE2.DATA_ENTRADA)
                                                                      FROM tb_Entradas as tbE2));
                 
                 -- Seleciono o id do lote
             SET @ID_LOTE = (SELECT ID_LOTE
                                    FROM tb_Items_Entrada
                                    WHERE ID_ENTRADA = @ID_ENTRADA
                                    AND ID_ITEM = @IDPRODUTO);
         -- Seleciono a quantidade
         SET @QUANTIDADE = (SELECT
                                  QUANTIDADE
                                  FROM tb_Items_Entrada
                                  WHERE ID_ENTRADA = @ID_ENTRADA
                                  AND ID_ITEM = @IDPRODUTO
                                  AND ID_LOTE = @ID_LOTE);
                                                                
                
       
         -- Se a Quantidade do lote for > que a quantidade passada por parâmetro
         IF(@QUANTIDADE >= @QTD)
         BEGIN
         
           -- Faz a subtração
           SET @QUANTIDADE = @QUANTIDADE - @QTD;
         
           -- Atualiza a quantidade do Lote
           UPDATE
                   tb_Items_Entrada
                       SET
                          QUANTIDADE = @QUANTIDADE
                       WHERE
                         ID_ENTRADA = @ID_ENTRADA
                         AND ID_ITEM = @IDPRODUTO
                         AND ID_LOTE = @ID_LOTE
             END
             -- Senão, se a quantidade que for passada por parametro for maior
             ELSE
             BEGIN
            -- Enquanto a quantidade for maior que zero
            WHILE(@QUANTIDADE > 0)
            BEGIN
                
                -- Irá subtrair a quantidade
                        SET @QUANTIDADE =  @QTD - @QUANTIDADE;
                                
                                -- Zera a quantidade do lote mais antigo 
                    UPDATE
                          tb_Items_Entrada
                          SET
                             QUANTIDADE = 0
                          WHERE
                                ID_ENTRADA = @ID_ENTRADA
                                AND ID_ITEM = @IDPRODUTO
                                AND ID_LOTE = @ID_LOTE
         
                                   
                                       --Pega o ID da entrada do segundo lote mais antigo
SET @ID_ENTRADA = (SELECT TOP 1 tbE1.ID_ENTRADA 
                   FROM tb_Entradas as tbE1 
                   WHERE tbE1.DATA_ENTRADA > (SELECT MIN(tbE3.DATA_ENTRADA) 
                                                                                                                                                               FROM tb_Entradas as tbE3));
                                        
                                           -- Pego o ID deste Lote                                     
 SET @ID_LOTE  = (SELECT ID_LOTE
                   FROM tb_Items_Entrada
                   WHERE ID_ENTRADA = @ID_ENTRADA
                   AND ID_ITEM = @IDPRODUTO);
                                          
                                           -- Pego a Quantidade deste Lote
SET @QTD = (SELECT QUANTIDADE
            FROM tb_Items_Entrada
            WHERE ID_ENTRADA = @ID_ENTRADA
            AND ID_ITEM = @IDPRODUTO
            AND ID_LOTE = @ID_LOTE);
                                                
                                                
                                                 
                                 -- Se a quantidade for  >= a Zero
           IF(@QUANTIDADE >= 0)
            BEGIN
                                                      
                --Subtraio a quantidade deste Lote
             SET @QUANTIDADE = @QUANTIDADE - @QTD;
                                                  
                -- Atualizo a Quantidade do Lote
                UPDATE
                     tb_Items_Entrada
                     SET
                       QUANTIDADE = @QUANTIDADE 
                     WHERE
                       ID_ENTRADA = @ID_ENTRADA
                       ID_ITEM = @IDPRODUTO
                       AND ID_LOTE = @ID_LOTE
              END
        END
              
    END
            
END

Ao invés de responder sua questão, vou lhe dar uma alternativa.

Já tentou realizar todo esse procedimento com apenas um update?

Quando trabalhamos no banco de dados, operações em conjunto são geralmente mais eficientes do que linha a linha.

Você pode fazer um Update com From no Sql Server.

Faça um select que retorne para cada lote, a soma de produtos daquele tipo nos lotes anteriores.

No seu caso ficaria algo assim:

Lote 1 - 400 - 0 (não há lotes anteriores)
Lote 2 - 50 - 400 ( que existe em Lote 1)
Lote 3 - 50 - 450 ( que existem em Lotes 1 e 2)

Com esse resultado, dá pra fazer o update de uma vez só.

Um outro aviso, não sei se mudou, mas não era considerado uma boa prática nomear procedures com o prefixo SP.