As transações são uma serie de modificações realizadas no interior de um processo sobre dados relacionados. Uma transação não é guardada permanentemente no banco até que a transação seja validada. Se não for completada uma transação, seja porque for cancelada ou por um evento externo, as modificações não são guardadas.
Durante uma transação, todas as mudanças realizados aos dados do banco dentro do processo são armazenados localmente em um buffer temporário. Se a transação for aceita com VALIDATE TRANSACTION, as mudanças são guardadas de maneira permanente. Se a transação for cancelada com CANCEL TRANSACTION, as mudanças não são guardadas. Em todos os casos, nem a seleção atual nem o registro atual são modificados pelos comandos de gestão de transações.
A partir da versão 11, 4D é compatível com transações aninhadas, ou seja, transações em vários níveis hierárquicos. O número de subtransações autorizadas é ilimitado. O comando Transaction level permite conhecer o nível atual de transação no qual se executa o código.
Quando utiliza transações aninhadas, o resultado de cada subtransação depende da validação ou cancelação da transação de nível superior. Se for confirmada a transação de nível superior, os resultados das subtransações são confirmados (confirmação ou cancelamento). Do contrário, se a transação superior for cancelada, todas as subtransações são canceladas, sem importar seus resultados.
As transações aninhadas podem gerar disfunções nos bancos desenvolvidas com versões anteriores de 4D, por esta razão esta opção está desativada por padrão nos bancos convertidos (as transações ficam limitadas a um só nível). Se deseja aproveitar as transações em vários níveis em um banco convertido, deve ser indicado explicitamente selecionando a opção Permitir transações aninhadas na página “Aplicação/Compatibilidade” das Preferências da aplicação.
Esta opção aparece apenas em bancos de dados convertidos. Por padrão, não está selecionada e é específica para cada banco. Não tem efeito nas transações realizadas no motor SQL de 4D. As transações SQL sempre são multinível.
Neste exemplo, o banco é um sistema de faturação simple. As linhas das faturas são armazenadas em uma tabela chamada [Linha_Fatura], a qual está relacionada com a tabela [Faturas] por uma relação entre os campos [Faturas]NumeroFaturas e [Linha_Fatura]NumeroFaturas. Quando se adiciona uma fatura, um número único é calculado utilizando o comando Sequence number. A relação entre [Faturas] e [Linha_Fatura] é uma relação automática Muitos a um. A caixa de seleção Autoatribuir valor no subformulário está selecionada.
A relação entre [Linha_Fatura] e [Partes] é manual.
![](../../picture/35829/pict35829.EN.png)
Quando um usuário introduz uma fatura, são executadas as seguintes ações:
- Adição de um registro na tabela [Faturas].
- Adição de vários registros na tabela [Linha_Fatura].
- Atualização do campo [Partes]Em_Depósito de cada parte listada na fatura.
Este exemplo é uma situação típica na qual necessita utilizar uma transação. Necessita ter certeza de que vai poder salvar todos estes registros durante a operação ou de que poder cancelar a transação se um registro não puder ser adicionado ou atualizado. Em outras palavras, deve guardar os dados relacionados.
Se não utilizar uma transação, não pode garantir a integridade de dados lógica de seu banco. Por exemplo, se um registro da tabela [Partes] estiver bloqueado, não poderá atualizar a quantidade armazenada no campo [Partes]Em_Depósito. Este campo ficará então logicamente incorreto. A soma das partes vendidas e restantes em depósito não serão iguais a quantidade original introduzida no registro. Pode evitar tal situação utilizando as transações.
Há várias maneiras de introduzir dados utilizando transações:
1. Pode administrar as transações utilizando os comandos de transação START TRANSACTION, VALIDATE TRANSACTION e CANCEL TRANSACTION. Pode escrever, por exemplo:
2. Para reduzir os bloqueios de registros durante a entrada de dados, pode também selecionar administrar transações a partir do método de formulário e acessar as tabelas em READ WRITE apenas quando seja necessário.
Você realiza a entrada de dados utilizando o formulário de entrada para [Faturas], o qual contém a tabela relacionada [Faturas]Linhas em um subformulário. O formulário tem dois botões: bCancel e bOK, ambos são botões sem ações.
O loop de adição é convertido em:
Note que a tabela [Partes] está em modo de acesso "apenas leitura" durante a entrada de dados. O acesso leitura/escrita estará disponível apenas se os dados forem confirmados.
A transação é aberta no método de formulário de entrada da tabela [Faturas]:
Se clicar no botão bCancel, a entrada e a transação devem ser canceladas.
Este é o método de objeto do botão bCancel:
Se clicar no botão bOK, a entrada e a transação devem ser aceitas. Este é o método de objeto do botão bOK:
Neste código, chamamos ao comando CANCEL sem importar em qual botão o usuário clique. O novo registro não está validado por uma chamada a ACCEPT, mas pelo comando SAVE RECORD. Além disso, note que SAVE RECORD é chamado imediatamente antes que o comando VALIDATE TRANSACTION. Portanto, guardar o registro [Faturas] é na verdade parte da transação. Chamar o comando ACCEPT também confirmaria o registro, mas neste caso a transação será validada antes de que o registro [Faturas] seja guardado. Em outras palavras, o registro seria guardado fora da transação.
Dependendo de suas necessidades, pode personalizar seu banco, como é mostrado nestes exemplos. No último exemplo, a gestão de bloqueio de registros da tabela [Partes] pode ser mais desenvolvida.