[firebase-br] Recalculo de saldo (Trigger)
Fabiano Lima
frguitar em bol.com.br
Seg Set 26 12:03:47 -03 2011
Cara, nem sei como te agradecer, valew mesmo.
Só uma coisinha no final, a atualização posterior retorna o saldo anterior dela mesma + o credito, não teria de ser o saldo anterior da linha anterior?
ex:
saldo_ini = 100
apos inserir dados
lanc_id credito debito saldo
1 1 0 101
2 1 0 102
3 1 0 103
após o update na linha no id 2
lanc_id credito debito saldo
1 1 0 101
2 10 0 113
3 1 0 104
att
Fabiano
____________________________________________
Em 26/09/2011 10:28, andre conrado < acf.andre em gmail.com > escreveu:
Ok amigo, seu problema é de lógica, então vamos a ela:
Na sua TRIGGER o primeiro passo está correto, isto é, vc obtém o saldo
somando as colunas a CREDITO, DEBITO e SALDO_INI. Até está razoável,
mas eu faria um diferente, pense o seguinte:
- Quanto o primeiro lançamento for inserido ou alterado o campo saldo
este lançamento precisa ser atualizado, o que não ocorre em seu
código, já que o FOR SELECT só está tratando os registros posteriores.
Então está faltando depois dos SELECTs de somatório o seguinte linha:
NEW.SALDO = BANCOSALDO + NEW.CREDITO - NEW.DEBITO;
(Imagino o campo SALDO não esteja sendo calculado via aplicação)
Vamos agora ao conteúdo do FOR SELECT:
1º - Sua rotina está colocando no SALDO o valor total dos créditos e
débitos até o lançamento atual, isso desconsidera os créditos e
débitos posteriores que interferem nos cálculos posteriores.
2º - Quanto o UPDATE é executado uma nova chamada a TRIGGER será
gerada, o que fará com que nova chamada seja gerada até que não acha
mais lançamento. Sendo assim, as atualização não precisariam ser
chamadas dentro de um FOR SELECT.
Tá ficando confuso néh, fiz está colocações para complexidade do
rotina acima, então vamos começar todo de novo. Tente assim, e me diga
se funciona:
// TRIGGER para Atualiza do SALDO atual
CREATE OR ALTER trigger trg_saldo_up_before for lanc
active after before position 2
AS
DECLARE VARIABLE LANCAMENTO INTEGER;
DECLARE VARIABLE SALDOANTERIOR INTEGER;
BEGIN
/* Primeiro passo, obter o saldo anterior, se existirem
lançamentos anteriores então obtenho o saldo do último lançamento
caso contrário obtenho o saldo inicial do banco */
IF (EXISTS(SELECT 0 FROM LANC WHERE LANC_ID < NEW.LANC_ID)) THEN
SELECT FIRST 1 SALDO FROM LANC ORDER BY LANC_ID DESC INTO
:SALDOANTERIOR;
ELSE
SELECT SALDO_INI FROM CADBANCO WHERE CCONTA = NEW.CCONTA INTO
:SALDOANTERIOR;
// Calcula o saldo atual
NEW.SALDO = SALDOANTERIOR + NEW.CREDITO - NEW.DEBITO;
END
// TRIGGER para atualizar o SALDO dos lançamento subsequentes
CREATE OR ALTER trigger trg_saldo_up_after for lanc
active after update position 2
AS
DECLARE VARIABLE LANCAMENTO INTEGER;
DECLARE VARIABLE SALDOANTERIOR INTEGER;
BEGIN
// Localiza o próximo lançamento
SELECT FIRST 1 LANC_ID FROM LANC WHERE LANC_ID > NEW.LANC_ID
ORDER BY LANC_ID INTO :LANCAMENTO;
// Simula a alteração do próximo lançamento para que o FIREBIRD
gere uma nova chamada a TRIGGER de atualização do SALDO
UPDATE LANC SET CREDITO = CREDITO WHERE LANC_ID = :LANCAMENTO;
END
Dúvida ou críticas? Não fique com elas... rsrs
abçs
______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use: http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://firebase.com.br/pesquisa
Mais detalhes sobre a lista de discussão lista