none
Atualização do Saldo de Conta Corrente RRS feed

  • Pergunta

  • Bom dia pessoal !

    Tenho certeza que neste grupo só tem feras em BD SQL Server, então estou recorrendo a vocês para uma ajuda.

    Se alguém puder examinar a query abaixo e me dizer se tem algum erro ou se esta correta, ficarei muito grato.

    ************
    ESTA ROTINA EU USO PARA ATUALIZAR O SALDO DO CONTA CORRENTE CONTÁBIL, passando os dados referente ao IdConta e DtLancto a partir da qual os saldos de cada linha de lançamento serão atualizados. Ex: Conta = 57, Data 24/09/2019, os saldos dos lançamentos serão atualizados do dia 24/09/2019 em diante, cuja conta seja 57.
    *************

    O problema que estou tendo é "as vezes o saldo do meu conta corrente é atualizado errado", pois pega o saldo inicial de uma data inferior a data inicial informada.

    Para leitura eu uso o indice IX_Lancto (IdConta (ASC), DtLancto (ASC), NatLancto (ASC), IdLote (ASC), Ordem (ASC)).

    --************************

    USE [dbc0102001]
    GO

    DECLARE @IdConta as int,
            @DtLancto as date,
        @VlrSaldo as decimal(16,2);

    SET @IdConta = 57;  -- somente exemplo
    SET @DtLancto = '2019-09-24';  -- somente exemplo
    SET @VlrSaldo = 0;

    SELECT TOP(1) @VlrSaldo = VlrSaldo 
      FROM ctLancto WITH (INDEX(IX_ctLancto)) 
     WHERE IdConta = @IdConta AND DtLancto < @DtLancto
     ORDER BY DtLancto DESC, NatLancto ASC, IdLote ASC, Ordem ASC

    UPDATE ctLancto
       SET @VlrSaldo = @VlrSaldo + (CASE WHEN TipoPartida = 'D' THEN (VlrLancto) WHEN TipoPartida = 'C' THEN (VlrLancto * -1) ELSE 0 END), VlrSaldo = @VlrSaldo
      FROM ctLancto WITH (INDEX(IX_ctLancto)) 
     WHERE IdConta = @IdConta AND DtLancto >= @DtLancto
    GO

    --************************

    obrigado !



    • Editado Pedro Palma terça-feira, 15 de outubro de 2019 18:11
    terça-feira, 15 de outubro de 2019 14:51

Respostas

Todas as Respostas

  • Deleted
    terça-feira, 15 de outubro de 2019 15:04
  • Obrigado Diniz.
    Vou testar e retornarei com o resultado.
    terça-feira, 15 de outubro de 2019 15:28
  • Deleted
    terça-feira, 15 de outubro de 2019 15:28
  • Oi Luiz,

    Obrigado pela explicação que vc me deu.
    Tenho um pouco de dificuldade em SQL, meu foco é em programação C#.
    Quero ver se entendi bem a sua explicação (código #1 v3).

    1) Quando o SELECT é executado, o registro encontrado fica na agulha, ou melhor, é o registro corrente; e
    2) Quando o UPDATE é executado, inicia a atualização dos registros a partir do registro corrente.

    Correto ?
    Sendo correto, então não preciso guardar o valor do saldo anterior.

    obrigado,

    terça-feira, 15 de outubro de 2019 16:36
  • Pedro,

    Estou entrando no post para colaborar, pois o mesmo já esta bem conduzido.

    Em relação as suas perguntas perguntas, vou tentar responder:

    1) Quando o SELECT é executado, o registro encontrado fica na agulha, ou melhor, é o registro corrente; e

    Como o Select esta utilizando o operador Top 1, neste caso somente uma única linha esta sendo retornada, sim este é o registro corrente o qual foi pesquisado, identificado e apresentando em tela pelo SQL Server.
    2) Quando o UPDATE é executado, inicia a atualização dos registros a partir do registro corrente.

    Isso mesmo, como esta sendo utilizando uma CTE, conhecida como tabela de expressão comum, toda estrutura deste objeto enquanto o mesmo encontra-se em uso será composta única e especificamente por este registro e seu conjunto de valores, o Update vai ser processado para atender o que foi colocado como condição no comando Case atulizando o valor da variável ou parâmetro @VlrSaldo para o conjunto de linhas de registros existentes na CTE Linha_Lancto, ou seja, basicamente o registro único que esta contido dentro dela.

    Pois bem, espero ter ajudado, abraços.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    terça-feira, 15 de outubro de 2019 17:31
  • Deleted
    terça-feira, 15 de outubro de 2019 17:34
  • Obrigado Junior !

    Eu fiz uma alteração no post inicial, incluindo uma observação sobre o uso da rotina, assim fica mais claro a necessidade da rotina.

    Bom, eu entendi bem a sua explicação e agradeço a sua interação neste post.

    abs,
    terça-feira, 15 de outubro de 2019 18:16
  • Obrigado José Diz !

    Peço desculpas por ter direcionado a você com outro nome (Diniz e Luiz), não sei onde estava com a cabeça (kkkk), acho que esta rotina esta me deixando louco.
    Eu fiz uma alteração no post inicial, incluindo uma observação sobre o uso da rotina, assim fica mais claro a necessidade dela.
    Bom, eu entendi bem a sua explicação e agradeço muito.

    Fiz vários testes e de fato o registro corrente é atualizado, mas minha necessidade é que atualize todos os registros a partir de uma informação (que sejam iguais ao IdConta e igual ou maior que a DtLancto informada), seguindo a ordem do indice IX_ctLancto.

    att,
    terça-feira, 15 de outubro de 2019 18:24
  • Obrigado Junior !

    Eu fiz uma alteração no post inicial, incluindo uma observação sobre o uso da rotina, assim fica mais claro a necessidade da rotina.

    Bom, eu entendi bem a sua explicação e agradeço a sua interação neste post.

    abs,

    Pedro,

    Ok, obrigado.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    terça-feira, 15 de outubro de 2019 18:35
  • Pedro,

    Então neste caso, você não deseja que seja retornado somente uma linha, mas sim todas que satisfazem a sua condição?

    Se for isso, acredito que ao remover o comando Top 1, você terá o retorno de todas as linhas, com isso o Update que será realizado vai justamente fazer a atualização na coluna VlrSaldo de acordo com as regras do comando Case e respeitando a junção aplicada entre a tabela ctLancto e a CTE.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    terça-feira, 15 de outubro de 2019 18:39
  • Junior,

    Da forma que eu postei logo no início, as vezes o saldo inicial é pego corretamente, as vezes o saldo inicial é pego de outra data ficando errado, isso acontece no comando SELECT, dai em diante, comando UPDATE, os saldos de todos os registros que satisfaçam a igualdade do IdConta são atualizados, tomando como base o saldo inicial obtido no comando SELECT.  

    Uma pergunta de leigo:
    Será que o Indice pode estar provocando esta situação ?



    • Editado Pedro Palma terça-feira, 15 de outubro de 2019 19:08
    terça-feira, 15 de outubro de 2019 18:56
  • Deleted
    terça-feira, 15 de outubro de 2019 19:22
  • Deleted
    • Marcado como Resposta Pedro Palma terça-feira, 15 de outubro de 2019 20:44
    terça-feira, 15 de outubro de 2019 19:58
  • Bingo José Diz !

    Antes de ler o seu comentário, eu estava analisando os dados de um cliente que continha o erro em pauta.
    Após uma analise minuciosa, acabei enxergando o erro que é exatamente o que vc postou, ou seja, a ORDER BY do SELECT estava errada.
    Alterando a ORDER BY a rotina ficou TOP, também fiz a alteração que vc propôs   
    SET @VlrSaldo= VlrSaldo=  @VlrSaldo + (CASE WHEN TipoPartida = 'D' THEN (VlrLancto) WHEN TipoPartida = 'C' THEN (VlrLancto * -1) ELSE 0 END)

    Vou colocar em produção o seguinte comando:

    USE [dbc0102001]
    GO

    DECLARE @IdConta as int,
                 @DtLancto as date,
                  @VlrSaldo as decimal(16,2);

    SET @IdConta = 57;  -- somente exemplo
    SET @DtLancto = '2019-09-24';  -- somente exemplo
    SET @VlrSaldo = 0;

    SELECT TOP(1) @VlrSaldo = VlrSaldo 
      FROM ctLancto WITH (INDEX(IX_ctLancto)) 
     WHERE IdConta = @IdConta AND DtLancto < @DtLancto
     ORDER BY DtLancto DESC, NatLancto DESC, IdLote DESC, Ordem DESC

    UPDATE ctLancto
       SET @VlrSaldo = VlrSaldo = @VlrSaldo + (CASE WHEN TipoPartida = 'D' THEN (VlrLancto) WHEN TipoPartida = 'C' THEN (VlrLancto * -1) ELSE 0 END)
      FROM ctLancto WITH (INDEX(IX_ctLancto)) 
     WHERE IdConta = @IdConta AND DtLancto >= @DtLancto
    GO

    att,

    terça-feira, 15 de outubro de 2019 20:42
  • Oi José Diz,

    1) A versão do BD é 2014;
    2) Número aproximado de lançamentos por conta, depende muito da empresa. Tem conta que é pouquissimo lançamento (até 100), tem conta que chega a 10 mil. O UPDADE ocorre em poucas contas, pois atualiza o saldo a partir dos dados informados (IdConta e DtLancto).
    3) Este código ficará em produção.
    4) Não tem problema com concorrência pois o código é executado dentro de um bloco TransactionScope.
    5) Eu vou testar todas as alternativas que passou.

    Mais uma vez, meu muito obrigado. Voce me quebrou um galhão e me explicou muita coisa, por isso serei sempre grato.

    obrigado,

    terça-feira, 15 de outubro de 2019 21:02
  • Deleted
    terça-feira, 15 de outubro de 2019 21:06
  • Olá José Diz,

    Acabei de subir a versão que eu propus.
    Fiz vários testes e esta rodando maravilhosamente bem.
    Amanhã o cliente é quem vai testar, kkkk, pois estará fazendo lançamentos de diversas formas, então poderei estar monitorando para saber se esta tudo OK.
    A respeito dos seus códigos, em especial ao #3 v3, também estarei testando em ambiente de desenvolvimento e darei o feedback do resultado.

    abs,
    terça-feira, 15 de outubro de 2019 22:15
  • Junior,

    Da forma que eu postei logo no início, as vezes o saldo inicial é pego corretamente, as vezes o saldo inicial é pego de outra data ficando errado, isso acontece no comando SELECT, dai em diante, comando UPDATE, os saldos de todos os registros que satisfaçam a igualdade do IdConta são atualizados, tomando como base o saldo inicial obtido no comando SELECT.  

    Uma pergunta de leigo:
    Será que o Indice pode estar provocando esta situação ?



    Pedro,

    O índice não iria fazer isso não, mas sim a maneira com que você esta pesquisando os dados ou até mesmo ordenando.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    quarta-feira, 16 de outubro de 2019 13:30
  • Oi Junior,

    Obrigado pela sua ajuda e participação neste post.

    Ontem a noite eu subi as alterações e coloquei em produção conforme comentário feito com o José Diz.
    Hoje dois clientes usaram o dia todo sem nenhuma reclamação.
    A poucos minutos atrás, fiz uma analise dos dados a respeito dos saldos, pude constatar que estão corretos. Isto significa que o código inserido esta funcionando.

    abs,

    quarta-feira, 16 de outubro de 2019 21:09
  • Oi Junior,

    Obrigado pela sua ajuda e participação neste post.

    Ontem a noite eu subi as alterações e coloquei em produção conforme comentário feito com o José Diz.
    Hoje dois clientes usaram o dia todo sem nenhuma reclamação.
    A poucos minutos atrás, fiz uma analise dos dados a respeito dos saldos, pude constatar que estão corretos. Isto significa que o código inserido esta funcionando.

    abs,

    Pedro,

    Que bom, fico feliz em poder ajudar, estou neste dias muito sobrecarregado devido a questões profissionais, mas dentro do possível vou acompanhando.

    Agradeço a atenção e no que for possível contem comigo.


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    quarta-feira, 16 de outubro de 2019 22:17