Dúvida em SP
23/04/2010
0
Estou com uma dúvida na SP abaixo a qual atualiza a quantidade na tabela Produto e inclui um registo na tabela MovEstoque.
Por exemplo, se houver duas transações, A e B, ao mesmo tempo para atualizar o mesmo produto.
- vamos considerar que a transação A inicia antes que a B.
- a transação A lê a qtd de produto para a variável xQtd, e a transação B também, digamos xQtd = 100 (parte 1 do código).
- a transação A atualiza a qtd de produto (parte 2 do código) e inclui um registro na tabela MovEstoque (parte 3) com as quantidades anterior e atual de produto.
- neste momento a transação B fica aguardando a finalização da transação A.
- a transação A executa um commit.
- a transação B atualiza a tabela Produto.
- a transação B incui um registro na tabela MovEstoque. Entretanto o conteúdo da variável xQtd está errado, pois houve uma alteração na tabela Produto feita pela transação A, então, o campo QuantAnterior da tabela MovEstoque terá um valor incorreto.
Gostaria de saber se a análise do código está certa e como posso resolver o problema do valor que é passado para a variável xQtd, pois na tabela MovEstoque preciso ter nos campos QuantAnterior e QuantAtual as quantidades do produto anterior e atual.
CREATE OR ALTER PROCEDURE CONTROLA_ESTOQUE (
p_CodProd integer,
p_Quant numeric(9,4))
as
declare variable xQtd Numeri(9,4);
begin
/* parte 1 - obtém a quantidade do produto que será a qtd anterior do movimento no estoque */
Select QuantEstoque
From Produto
Where Codigo = :p_CodProd
Into :xQtd;
/* parte 2 - atualiza a qtd de produtos */
Update Produto
Set QuantEstoque = QuantEstoque + (:p_Quant)
Where Codigo = :p_CodProd;
/* parte 3 - incluir um movimento no estoque */
Insert Into MovEstoque
(Id,
Data,
CodProduto,
QuantAnterior,
QuantAtual)
values
(gen_id(Gen_MovEstoque, 1),
current_date,
:p_CodProd,
:xQtd,
(:xQtd + :p_Quant));
end
Por exemplo, se houver duas transações, A e B, ao mesmo tempo para atualizar o mesmo produto.
- vamos considerar que a transação A inicia antes que a B.
- a transação A lê a qtd de produto para a variável xQtd, e a transação B também, digamos xQtd = 100 (parte 1 do código).
- a transação A atualiza a qtd de produto (parte 2 do código) e inclui um registro na tabela MovEstoque (parte 3) com as quantidades anterior e atual de produto.
- neste momento a transação B fica aguardando a finalização da transação A.
- a transação A executa um commit.
- a transação B atualiza a tabela Produto.
- a transação B incui um registro na tabela MovEstoque. Entretanto o conteúdo da variável xQtd está errado, pois houve uma alteração na tabela Produto feita pela transação A, então, o campo QuantAnterior da tabela MovEstoque terá um valor incorreto.
Gostaria de saber se a análise do código está certa e como posso resolver o problema do valor que é passado para a variável xQtd, pois na tabela MovEstoque preciso ter nos campos QuantAnterior e QuantAtual as quantidades do produto anterior e atual.
CREATE OR ALTER PROCEDURE CONTROLA_ESTOQUE (
p_CodProd integer,
p_Quant numeric(9,4))
as
declare variable xQtd Numeri(9,4);
begin
/* parte 1 - obtém a quantidade do produto que será a qtd anterior do movimento no estoque */
Select QuantEstoque
From Produto
Where Codigo = :p_CodProd
Into :xQtd;
/* parte 2 - atualiza a qtd de produtos */
Update Produto
Set QuantEstoque = QuantEstoque + (:p_Quant)
Where Codigo = :p_CodProd;
/* parte 3 - incluir um movimento no estoque */
Insert Into MovEstoque
(Id,
Data,
CodProduto,
QuantAnterior,
QuantAtual)
values
(gen_id(Gen_MovEstoque, 1),
current_date,
:p_CodProd,
:xQtd,
(:xQtd + :p_Quant));
end
Luiz Bertolazzi
Curtir tópico
+ 0
Responder
Posts
23/04/2010
Emerson Nascimento
sinceramente, nunca vi guardar a quantidade anterior e atual num registro. não faz sentido e não é recomendável.
imagine que um registro de movimentação seja excluído. todos os valores das colunas daquele registro "pra baixo" deverão ser recalculados.
o correto é que esses valores sejam apurados em tempo real.
e outra coisa: para casos como esse, NUNCA guarde valores em variáveis.
de qualquer forma, tente algo assim:
CREATE OR ALTER PROCEDURE CONTROLA_ESTOQUE (
p_CodProd integer,
p_Quant numeric(9,4))
begin
/* parte 1 - incluir um movimento no estoque */
Insert Into MovEstoque
(Id, Data, CodProduto, QuantAnterior, QuantAtual)
select
gen_id(Gen_MovEstoque, 1),
current_date,
Codigo,
QuantEstoque,
(QuantEstoque + :p_Quant)
from
Produto
where
Codigo = :p_CodProd;
/* parte 2 - atualiza a qtd de produtos */
Update Produto Set
QuantEstoque = (QuantEstoque + :p_Quant)
Where
Codigo = :p_CodProd;
end
imagine que um registro de movimentação seja excluído. todos os valores das colunas daquele registro "pra baixo" deverão ser recalculados.
o correto é que esses valores sejam apurados em tempo real.
e outra coisa: para casos como esse, NUNCA guarde valores em variáveis.
de qualquer forma, tente algo assim:
CREATE OR ALTER PROCEDURE CONTROLA_ESTOQUE (
p_CodProd integer,
p_Quant numeric(9,4))
begin
/* parte 1 - incluir um movimento no estoque */
Insert Into MovEstoque
(Id, Data, CodProduto, QuantAnterior, QuantAtual)
select
gen_id(Gen_MovEstoque, 1),
current_date,
Codigo,
QuantEstoque,
(QuantEstoque + :p_Quant)
from
Produto
where
Codigo = :p_CodProd;
/* parte 2 - atualiza a qtd de produtos */
Update Produto Set
QuantEstoque = (QuantEstoque + :p_Quant)
Where
Codigo = :p_CodProd;
end
Responder
Clique aqui para fazer login e interagir na Comunidade :)