Re: [firebase-br] Campo Auto-Incremento Sem Perda da Seqüência..
Francisco Thiago
jeandeadlucky em yahoo.com.br
Qua Jul 13 10:52:09 -03 2005
Bem, para solucionar o caso das várias transações eu escrevi a seguinte
procedure baseado numa solução que vi em algum lugar na internet...
{Caso retorne -1, você recupera o valor do generator}
function TDmCadastro.GetCanceledGenerator(const Usuario, Senha: WideString;
GenName: String; Empresa: Integer): Integer;
var
li_Tmp_Result :Integer;
li_Apply :Integer;
begin
Result := -1;
li_Tmp_Result := -1;
li_Apply := 1;
try
try
repeat
if cdsCanceled_Generator.Active then
cdsCanceled_Generator.Close;
cdsCanceled_Generator.Params[0].AsString := UpperCase(GenName);
cdsCanceled_Generator.Params[1].AsInteger := Empresa;
cdsCanceled_Generator.Open;
if Not cdsCanceled_Generator.Fields[0].IsNull then
begin
li_Tmp_Result := cdsCanceled_Generator.Fields[0].AsInteger;
cdsCanceled_Generator.SetOptionalParam('USUARIO', Usuario, True);
cdsCanceled_Generator.SetOptionalParam('SENHA', Senha, True);
cdsCanceled_Generator.Delete;
li_Apply := cdsCanceled_Generator.ApplyUpdates(0)
end;
until (li_Apply = 0) or (cdsCanceled_Generator.Fields[0].IsNull);
if li_Apply = 0 then
Result := li_Tmp_Result;
except
Result := -1;
end;
finally
cdsCanceled_Generator.Close;
end;
end;
procedure TDmCadastro.SetCanceledGenerator(GenName: String; Valor,
Empresa: Integer);
begin
with cdsExec do
begin
if active then close;
CommandText := 'insert into CANCELED_GENERATOR (CCLG_GEN_NAME,
CCLG_GEN_ID, EMPR_CODIGO) VALUES(:GenName,:VALOR, :Empresa)';
Params[0].AsString := GenName;
Params[1].AsInteger := Valor;
Params[2].AsInteger := Empresa;
Execute;
end;
end;
Existe algum código para autenticação de usuários que pode ser
desconsiderado (.SetOptionalParam('USUARIO', Usuario, True);)
Mas a lógica seria a seguinte:
Eu pego o valor da tabela;
E tento excluir ele
Consegui excluir:
Ótimo, já estou com o valor
Não consegui excluir
Vou tentar pegar outro valor
Caso não consiga, ou não existam valores cancelados, eu simplesmente
retorno -1... com isso, o programa vai saber que o valor correto seria o do
gen_id(generator,1);
Qqr coisa estamos ae
Francisco Thiago de Almeida
Enter&Plug Sistemas
Divisão: Desenvolvimento / Banco de dados
Franca - SP
----- Original Message -----
From: "Giovani Benedetti Penha" <giovani em cooperval.com>
To: "FireBase" <lista em firebase.com.br>
Sent: Wednesday, July 13, 2005 10:33 AM
Subject: Re: [firebase-br] Campo Auto-Incremento Sem Perda da Seqüência..
> > Tome apenas cuidado com as transações na tabela Gen_Cancel... pois
> você pode ter problemas (como pegar o mesmo número).
>
> Ou seja, parece que essa solução também não é livre de erros. Na verdade,
> quando existem várias transações, será difícil você garantir exclusão
> mútua para assegurar que duas delas não obtenham um valor igual ao mesmo
> tempo. Inclusive por isso o generator possui essa característica: pegou um
> novo valor, não tem como voltar atrás.
> Talvez os artigos citados em outros emails resolvam seu problema...
>
> []´s
> Giovani Benedetti Penha
>
> Francisco Thiago escreveu:
>
>> O gen_id(asdf,0) + 1 é suicídio pelo fator que você considerou antes
>> "(...) e se duas transações (...)".
>>
>>> E fiquei com uma dúvida agora também: ao iniciar uma transação,
>>> atualizar um generator e dar um rollback na transação, o valor do
>>> generator voltaria ao que era antes da transação?
>>
>>
>> O gen_id foge do contexto Transacional, ou seja, quando você incrementa
>> um generator ele é incrementado e pronto...
>> Voltar atrás o valor do generator é outro pulo do prédio...
>>
>> Basicamente, o que você pode fazer é o seguinte:
>>
>> 1) Você precisa do código no momento do Insert
>>
>> Você recupera o valor do generator (gen_id(generator,1)) e grava numa
>> variável, ou até mesmo já no campo chave. Se o usuário confirmar a
>> gravação, sem problemas... agora, caso ele cancele, você vai ter que
>> fazer o seguinte:
>>
>> Grave este valor numa tabela do tipo :
>> create table Gen_cancel (
>> Nome_generator
>> Valor_Generator
>> );
>>
>> Daí sempre que você for recuperar o valor de um Generator, consulte antes
>> esta tabela. Se tiver algo nela, use este valor e o delete no mesmo
>> instante, caso contrário, pegue o resultado do gen_id(generator,1).
>>
>> Você vai precisar escrever uma procedure (ou uma SP) pra automatizar
>> isso. Tome apenas cuidado com as transações na tabela Gen_Cancel... pois
>> você pode ter problemas (como pegar o mesmo número).
>>
>>
>> Acredito que tenha algum material sobre o assunto na ClubeDelphi, ou até
>> mesmo na Firebase.... Seria interessante vc dar uma olhada...
>>
>> []'s
>>
>> Francisco Thiago de Almeida
>> Enter&Plug Sistemas
>> Divisão: Desenvolvimento / Banco de dados
>> Franca - SP
>>
>> ----- Original Message ----- From: "Giovani Benedetti Penha"
>> <giovani em cooperval.com>
>> To: "FireBase" <lista em firebase.com.br>
>> Sent: Tuesday, July 12, 2005 5:03 PM
>> Subject: Re: [firebase-br] Campo Auto-Incremento Sem Perda da Seqüência..
>>
>>
>>> Allan,
>>> A meu ver, uma forma seria retornar um gen_id(gerador,0) do seu banco e
>>> atribuir +1 manualmente pelo código.
>>> O gen_id(gerador,0) não altera o valor do generator. Atribuindo +1 por
>>> código você "simularia" o próximo valor do gerador, mas sem alterar seu
>>> valor atual. Então, apenas se a inserção fosse confirmada, você chamaria
>>> o gen_id(gerador,1), para atualizar o valor do gerador. Porém, aí temos
>>> um problema grave: se existirem duas transações ativas ao mesmo tempo em
>>> dois clientes diferentes, as duas iriam obter o mesmo gen_id e tentariam
>>> gravar com a mesma chave, ocasionando problema de violação da chave
>>> primária. Mas se o sistema for executado por um único cliente, daí
>>> acredito que resolva seu problema.
>>> E fiquei com uma dúvida agora também: ao iniciar uma transação,
>>> atualizar um generator e dar um rollback na transação, o valor do
>>> generator voltaria ao que era antes da transação? Em teoria sim né? Se
>>> isso funcionasse, você poderia comitar a transação sempre que a inserção
>>> ocorresse ou rollback caso fosse cancelada. Alguém sabe o que
>>> aconteceria nesse caso?
>>>
>>> Espero ter ajudado mais do que confundido!
>>>
>>> []´s
>>> Giovani Benedetti Penha
>>>
>>>
>>> Allan Elias Ramos escreveu:
>>>
>>>> Olá pessoal, tudo bem? Espero que sim..
>>>>
>>>> Olha, não sei se tem algum jeito de fazer isso, mas minha dúvida é a
>>>> seguinte:
>>>>
>>>> Pra criar um campo auto-incremento no Firebird, é necessário um
>>>> Generator e uma Trigger. Isso eu sei fazer, e consigo também gerar o
>>>> número no campo antes de salvar o registro (eu preciso disso pq preciso
>>>> desse código). Mas assim, se eu criar um novo registro e não salvar
>>>> ele, por acaso eu cancelar a inserção de dados, esse código gerado se
>>>> perde, por exemplo.
>>>>
>>>> Código 1 - Salvo
>>>> Código 2 - Salvo
>>>> Código 3 - Cancelado
>>>> Código 4 - Salvo
>>>>
>>>> A idéia seria não perder o código 3, ficando assim:
>>>>
>>>> Código 1 - Salvo
>>>> Código 2 - Salvo
>>>> Código 3 - Cancelado
>>>> Código 3 - Salvo
>>>>
>>>> Eu sei q, por exemplo, no Access ele funciona assim.. quando um código
>>>> gerado automaticamente não é usado, ele nao é descartado, é guardado
>>>> pra uso posterior.. tem como fazer isso no Firebird?
>>>>
>>>> Só pra deixar claro, quero esse funcionamento só no caso de um
>>>> cancelamento na inserção do registro. Sei que, quando um registro é
>>>> deletado, o código não pode mais ser aproveitado.
>>>>
>>>> Agradeço desde já a ajuda.. abraços..
>>>>
>>>>
>>>> Allan Elias Ramos
>>>> ______________________________________________
>>>> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
>>>> Para editar sua configuração na lista, use o endereço
>>>> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
>>>> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>>>>
>>>>
>>>>
>>> ______________________________________________
>>> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
>>> Para editar sua configuração na lista, use o endereço
>>> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
>>> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>>>
>>>
>>> --
>>> No virus found in this incoming message.
>>> Checked by AVG Anti-Virus.
>>> Version: 7.0.323 / Virus Database: 267.8.13/47 - Release Date:
>>> 12/07/2005
>>>
>>
>>
>> _______________________________________________________ Yahoo! Acesso
>> Grátis - Internet rápida e grátis. Instale o discador agora!
>> http://br.acesso.yahoo.com/
>>
>>
>> ______________________________________________
>> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
>> Para editar sua configuração na lista, use o endereço
>> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
>> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>>
>>
>
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.bavs.com.br
> Para editar sua configuração na lista, use o endereço
> http://mail.firebase.com.br/mailman/listinfo/lista_firebase.com.br
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
>
> --
> No virus found in this incoming message.
> Checked by AVG Anti-Virus.
> Version: 7.0.323 / Virus Database: 267.8.13/47 - Release Date: 12/07/2005
>
_______________________________________________________
Yahoo! Acesso Grátis - Internet rápida e grátis.
Instale o discador agora! http://br.acesso.yahoo.com/
Mais detalhes sobre a lista de discussão lista