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