BLOQUEAR NOVAS LEITURAS EM BD FIREBIRD
Estou com uma situação e gostaria da ajuda de vocês. Tenho um sistema que realiza o controle de fluxo de documentos do lugar onde trabalho. Cada setor que necessita enviar um documento para fora deve ser cadastrado no sistema de forma que o setor de protocolo possa dar ciência ao usuário de que recebeu o documento. Cada documento cadastrado recebe um número sequencial que identifica o documento. Até duas semanas esse controle do número sequencial funcionou muito bem da forma como havia desenvolvido, porém, aconteceu de dois documentos sairem com numeração igual. Acredito que na hora da leitura do último registro tenha ocorrido, simultaneamente, com duas instâncias do programa e houve a duplicidade da informação. Portanto, há como bloquear a leitura da linha?
O que preciso é:
Quando uma instância do programa realizar a leitura da linha, ela seja bloqueada, nenhuma outra instância realiza a leitura (fica em modo de espera);
O programa vai realizar o cálculo para incrementação da sequência;
Vai realizar o update modificando o último valor e após desbloquear para nova leitura e incrementação e assim sucessivamente.
Utilizo Firebird 2.5.
Estás a usar o SELECT MAX() + 1 AS ProximoCodigo From Tabela... pra poder gerar o próximo campo de incremento? Se for, provavelmente aà tá o problema... Isso funciona apenas para banco de dados monousuário (multiusuário, dependendo da frequência de inserts até vai também, mas aà você vai estar contando com a sorte).
Pelo que eu saiba, Firebird não possui um tipo de dados de autoincremento... mas provavelmente deve ter alguma saÃda mais elegante, até porque é um banco projeto para multiusuário... Não tive tanto contato assim com Firebird...
Se ninguém responder até amanhã, eu dou uma pesquisada.
Abraços!
Acredito que esta não seja a melhor forma de se trabalhar com um campo que te servirá como chave primária. O ideal seria você criar um campo auto-incremento (utilizando generator e uma trigger), e em seguida [Ô]pegar[Ô] este valor para realizar os updates (você pode fazer um select no generator para isto).
Existe outra forma de se fazer isto. Antes de fazer o insert, você pode gerar uma GUID para gerar uma chave única (mas não deve ser a chave primaria), e utilizar ela como parâmetro para o seu select max(), será muito difÃcil que ocorra uma numeração com duplicidade após fazer desta forma, mas mesmo assim é importante utilizar o generator + trigger para esta operação, deixando que o banco de dados faça a geração do campo auto-numérico.
Acho que me expressei mal. Essa linha que eu preciso travar não possui chave primária, é só uma tabela com um único campo, que servirá como controle de numeração dos documentos que são enviados.
Como disse eu faço um select na tabela, como ela possui somente uma linha e um campo, eu pego o valor desse campo. Como o formato desse valor é XX/XXXX eu faço o tratamento dessa informação no programa. Eu separo o número da data, incremento e faço o update. é neste momento em que o programa está tratando esses dados que a tabela deve ser bloqueada para leitura. Após o Update ele destrava a tabela permitindo novas operações.
é preciso usar uma tabela com um registro, no caso, vc pode usar a tabela de sistema do FB. No Oracle usamos [ô]Dual[ô]
Experimenta isso num recordset:
SELECT GEN_ID(Nome_Generator_NUmeracao_Docs, 1) FROM RDB$DATABASE
Ao criar o generator no banco, vc precisa atribuir pra ele o último número dessa tabela. Deixe o banco trabalhar trabalhar pra vc.
Citação::
Pessoal,
Acho que me expressei mal. Essa linha que eu preciso travar não possui chave primária, é só uma tabela com um único campo, que servirá como controle de numeração dos documentos que são enviados.
Como disse eu faço um select na tabela, como ela possui somente uma linha e um campo, eu pego o valor desse campo. Como o formato desse valor é XX/XXXX eu faço o tratamento dessa informação no programa. Eu separo o número da data, incremento e faço o update. é neste momento em que o programa está tratando esses dados que a tabela deve ser bloqueada para leitura. Após o Update ele destrava a tabela permitindo novas operações.
ARCADYUM
Independente se você usa uma tabela para gerenciar uma chave única (como se fosse uma chave primária), o insert deverá ter uma chave primária também, para identificar que este registro será único no seu banco de dados, certo?
Você pode utilizar este número que você está gerando como um campo de referência, mas em conjunto com uma chave primária.
A falta disto é uma péssima prática, e acredito que você já esteja sofrendo as consequência de não planejar a sua estrutura de dados, o que torna o seu banco de dados muito redundante, passÃvel de erros. Não quero ser o chato, mas acredito que você deve repensar na estrutura de dados que definiu.
Citação::
Já que essa tabela só tem um campo, vou ser um pouquinho chato e insistir contigo com o Generator!
é preciso usar uma tabela com um registro, no caso, vc pode usar a tabela de sistema do FB. No Oracle usamos [ô]Dual[ô]
Experimenta isso num recordset:SELECT GEN_ID(Nome_Generator_NUmeracao_Docs, 1) FROM RDB$DATABASE
Ao criar o generator no banco, vc precisa atribuir pra ele o último número dessa tabela. Deixe o banco trabalhar trabalhar pra vc.
Também sou a favor de criar um generator para esta finalidade, é possÃvel fazer isto que você faz com o generator, basta pensar um pouquinho.
Um abraço.