Hoje vou mostrar como solucionar o erro Update error – lock required em suas customizações.
Recentemente um aluno me perguntou, que em uma das customizações que ele tinha, ocorria esse erro de Update error – lock required, e ele esta essencialmente relacionado quando você “desposiciona” uma tabela no meio do RecLock.
Como assim Daniel? Imagina o seguinte cenário, você deu um comando para incluir um registro ou alterar, via RecLock, vamos usar como exemplo, a tabela ZD1.
Nesse contexto, o Protheus por trás, preparou tudo que era necessário para você fazer a atualização dessa tabela. Mas e se no meio dessa atualização, você deu um DbSkip, um DbCloseArea, um DbGoTop, etc… qualquer comando que faça a tabela ZD1 ir para outro registro e sair do atual, o que irá acontecer?
Ele irá gerar esse erro, e não irá concluir o RecLock. Por exemplo, abaixo um trecho que ocasiona esse problema:
//Bibliotecas #Include "TOTVS.ch" #Include "TopConn.ch" /*/{Protheus.doc} User Function zTstLock Função que demonstra que não devemos desposicionar uma tabela ao dar um RecLock @type Function @author Atilio @since 13/07/2021 /*/ User Function zTstLock() Local aArea := GetArea() //Inclui o registro RecLock("ZD1", .T.) ZD1->ZD1_FILIAL := FWxFilial('ZD1') ZD1->ZD1_CODIGO := fUltCod() ZD1->ZD1_NOME := "Novo Artista" ZD1->(MsUnlock()) RestArea(aArea) Return Static Function fUltCod() Local cUltimo := "" DbSelectArea("ZD1") ZD1->(DbGoBottom()) cUltimo := Soma1(ZD1->ZD1_CODIGO) Return cUltimo
Notou algo estranho? Veja que existe uma função para buscar o último registro da tabela, e nela esta dando um DbGoBottom, durante o Lock, então encontramos o problema.
Qual seria e melhor solução então? O que eu recomendo para meus alunos, é colocar os valores do Lock em variáveis, antes de iniciar o RecLock, e como podemos ter filiais diferentes, para buscar o código, podemos optar por uma query SQL ou pela função GetSXENum.
Abaixo então, como ficou a função após os ajustes:
//Bibliotecas #Include "TOTVS.ch" #Include "TopConn.ch" /*/{Protheus.doc} User Function zTstLock Função que demonstra que não devemos desposicionar uma tabela ao dar um RecLock @type Function @author Atilio @since 13/07/2021 /*/ User Function zTstLock() Local aArea := GetArea() Local cZD1Filial := FWxFilial('ZD1') Local cCodigo := fUltCod() Local cNome := "Novo Artista" //Inclui o registro RecLock("ZD1", .T.) ZD1->ZD1_FILIAL := cZD1Filial ZD1->ZD1_CODIGO := cCodigo ZD1->ZD1_NOME := cNome ZD1->(MsUnlock()) RestArea(aArea) Return Static Function fUltCod() Local aArea := GetArea() Local cUltimo := StrTran(Space(TamSX3('ZD1_CODIGO')[1]), ' ', '0') Local cQuery := "" //Busca o último registro cQuery += " SELECT " + CRLF cQuery += " ISNULL(MAX(ZD1_CODIGO), '" + cUltimo + "') AS ULTIMO " + CRLF cQuery += " FROM " + CRLF cQuery += " " + RetSQLName('ZD1') + " ZD1 " + CRLF cQuery += " WHERE " + CRLF cQuery += " ZD1_FILIAL = '" + FWxFilial('ZD1') + "' " + CRLF TCQuery cQuery New Alias "QRY_ULT" //Incrementa 1 no último cUltimo := Soma1(QRY_ULT->ULTIMO) QRY_ULT->(DbCloseArea()) RestArea(aArea) Return cUltimo
Bom pessoal, por hoje é só.
Abraços e até a próxima.