Inclusão/alteração/deleção (via update) de dados no Protheus

Gostaria de saber qual a forma mais indicada de realizar inserções, alterações e deleções (via update) no Protheus.

Já vi exemplos de insert com (MAX(RE_C_N_O) + 1) em vez de RecLock, updates com TCSqlExec e também deleção, com (DE_L_E_T = '*'). Sei que minha dúvida é bem básica, mas gostaria de saber qual o indicado, por questões de desempenho, segurança e integridade. Se possível, vantagens e desvantagens.

Boa tarde,

O melhor mesmo por segurança é usar os execautos , mas em alguns casos não tem esse recurso como deve ser o seu caso, com isso o mas rapido é o update direto no banco (performance - TCSqlExec), pois o reclok é um insert no banco só que passando linha a linha do programa. no meu ver por segurança ou reclock ou direto no banco da no mesmo(não são seguros)

reclock não valida dados de sistema somente os campos null , única forma segura de validar é o execauto

Boa tarde

Dependendo da tabela que voce irá mexer não recomendo via banco, pois como bem sabemos não é o banco que faz o relacionamento entre as tabelas. Recomendo que use mesmo um programa ou função para fazer isso, pois ai o sistema é que irá gerenciar o relacionamento.

Christian,

O padrão do Protheus é trabalhar com RecLock, ao fazer um RecLock, é efetuado o lock do registro no DBAccess ou a criação do registro via DBAccess, que também que faz o incremento do R_E_C_N_O_ de maneira correta.

Além disso, o RecLock fica responsável pela gravação de logs e informações de lock, quando você tenta efetuar o lock de um registro e aparece aquela tela informando que o registro está em lock, com informações do usuário e rotina, o responsável por isso, também é o próprio RecLock.

O RecLock também tem o comportamento de retry, quando um registro está em lock, ele tenta pegar o registro de novo, ali aparece a dialog citada para abortar o processo, fazendo com que o RecLock retorne false.

Por fim, eu acho... O RecLock tem o comportamento de evitar deadlock (abendlock) em REST/SOAP entre outros, quando a thread não tem interface e você tenta fazer o lock do registro, não existe interface para cancelar o processo, logo, é possível que fique em retry, por conta disso quando em REST/SOAP, o retry tem um tempo de vida, ao esgotar esse tempo a thread é encerrada com informações sobre a tentativa de lock.

Legal, talvez tenha até mais informações sobre o RecLock, mas no momento não lembro! :)

Recomendo a utilização do RecLock para evitar qualquer problema, ele facilita inclusive o rastreamento caso ocorra algum problema, gerando logs no DBAccess etc.


Agora quandt a usar comandos DML, como INSERT, UPDATE, DELETE.

Ao fazer um insert utilizando MAX(R_E_C_N_O_) + 1, funciona? As vezes, existe a possibilidade de gerar erro de PK caso duas thread façam uma inserção ao mesmo tempo, afinal, antes do commit, o R_E_C_N_O_ será o mesmo para ambas.

Além disso, ao fazer uma inserção "na mão", o DBAccess acaba não sabendo sobre essa nova numeração de R_E_C_N_O_, com isso, também existe a chance de gerar error.log de PK.

Normalmente, para situações como essa, você acaba tendo de atualizar a tabela no DBAccess utilizando TCRefresh, que é uma função pesada, limpa todo o cache da tabela e refaz o mesmo.

Para delete e update, acredito que os riscos sejam menores, mas não deixam de existir, uma deleção física pode acarretar a situação complicada, como uma outra thread estar posicionada exatamente no registro deletado e estar fazendo uso do mesmo, diferente de uma deleção lógica (D_E_L_E_T_), isso pode gerar até mesmo exceções.


Para uma grande quantidade de inserções, foi criada a classe FWBulk, que utiliza de recursos do próprio DBAccess para efetuar a inserção em blocos, diminuindo o IO e aumentando muito a performance:

https://tdn.totvs.com/display/public/PROT/FWBulk