Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá a todos,
Gostaria de trocar uma informação com a comunidade. Como vocês fazem para manter no banco uma tabela, por exemplo, de movimentação de estoque e além disso ainda manter a quantidade atual de estoque do produto? Tenho visto muita gente guardar a informação do estoque atual na tabela de produtos, mas não acho isso adequado.
Pensei em colocar o saldo atual na mesma tabela de movimentação, dado sendo gravado ao invés de calculado via select, para não pesar o processamento.
Mas para não quebrar (muito) a normalização, pensei em fazer a atualização deste campo via trigger.
No insert e no update normal, funcionou bem.
Segue a ideia básica:
Tabela Estoque:
CREATE TABLE `estoque` (
`idMovEstoque` int(11) unsigned NOT NULL auto_increment,
`idProduto` int(10) unsigned NOT NULL,
`idFilial` int(10) unsigned NOT NULL,
`Data` datetime NOT NULL,
`TipoMov` char(1) collate latin1_general_ci default NULL,
`Operacao` char(2) collate latin1_general_ci NOT NULL,
`QtdeMov` decimal(12,4) default NULL,
`idMovimento` int(10) unsigned default NULL,
`SaldoEstoque` decimal(12,4) default NULL,
PRIMARY KEY (`idMovEstoque`),
KEY `FK_estoque` (`idProduto`,`idFilial`,`Data`),
KEY `FK_estoque1` (`idFilial`),
CONSTRAINT `FK_estoque1` FOREIGN KEY (`idFilial`) REFERENCES `filiais` (`idFilial`),
CONSTRAINT `FK_estoque2` FOREIGN KEY (`idProduto`) REFERENCES `produtos` (`idProduto`)
) ENGINE=InnoDB AUTO_INCREMENT=7774 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;
Triggers:
CREATE TRIGGER AtualizaSaldoEstoqueInsercao BEFORE INSERT ON estoque FOR EACH ROW BEGIN
Declare SaldoAnterior Numeric(12,2);
Select SaldoEstoque
From Estoque
Where (idFilial = New.idFilial) and (idProduto = New.idProduto)
Order By idMovEstoque Desc
Limit 0, 1
Into SaldoAnterior;
IF SaldoAnterior = NULL THEN
SET SaldoAnterior = 0;
END IF;
IF New.TipoMov = 'E' THEN
SET New.SaldoEstoque = SaldoAnterior + New.QtdeMov;
ELSE
SET New.SaldoEstoque = SaldoAnterior - New.QtdeMov;
END IF;CREATE TRIGGER `AtualizaSaldoEstoqueAtualizacao` BEFORE UPDATE ON `estoque` FOR EACH ROW BEGIN
Declare SaldoAnterior Numeric(12,2);
Select SaldoEstoque
From Estoque
Where (idFilial = New.idFilial) and (idProduto = New.idProduto) and
(idMovEstoque < New.idMovEstoque)
Order By idMovEstoque Desc
Limit 0, 1
Into SaldoAnterior;
IF SaldoAnterior = NULL THEN
SET SaldoAnterior = 0;
END IF;
IF New.TipoMov = 'E' THEN
SET New.SaldoEstoque = SaldoAnterior + New.QtdeMov;
ELSE
SET New.SaldoEstoque = SaldoAnterior - New.QtdeMov;
END IF;
END
Até aí funcionou tudo bem.
O problema é que eu gostaria de, quando uma determiada linha da tabela Estoque fosse alterada, ou apagada, essa alteração se propagasse para todos os lançamentos de Estoque que foram feitos a partir desta linha, de forma recursiva. Daí em pensei em fazer uma nova trigger:
CREATE
TRIGGER `AtualizaSaldoEstoqueAtualizacaoPos` AFTER UPDATE ON `estoque`
FOR EACH ROW BEGIN
Update Estoque SET SaldoEstoque = 0
Where (idProduto = New.idProduto) and
(idFilial = New.idFilial) and
(idMovEstoque > New.idMovEstoque)
Limit 1;
END;O objetivo deste último trigger é forçar o BEFORE UPDATE de todas as linhas subsequentes àquela que foi originalmente alterada, atualizando o campo SaldoEstoque.
Porém, o erro que ocorre quando tento atualizar uma linha (com update) é:
> Can't update table 'estoque' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
gostaria de saber como você faz esse tipo de tratamento em MySQL.
Peço desculpas pelo tamanho do post :)
Um abraço
Anderson Gaúcho
Carregando comentários...