gerar código automáticamente

Delphi

31/08/2005

Salve galera!
tenho aqui um procedure pra gerar código automaticamente... só que ele é limitado, pois ele gera um numero a partir do ultimo registro(table.last) da minha tabela. E se der um problema e o ultimo numero gerado pelo sistema for parar no meio da tabela? o sistema vai gerar um erro de violação de PrimaryKey... (esse erro está acontecendo comigo...)

Alguem teria um jeito melhor ai que pudesse varrer a tabela em busca do maior numero contido no campo ´código´ para que nao desse mais esse erro....

Segue abaixo o código atual:
----------------------------------
procedure TAutores.Btn_NovoClick(Sender: TObject);
var
Cod1 : Integer;
Cod2 : Integer;
begin
    Limpa_Edit;
    Edit_enable;

    // Contador de codigo
    
    DM.Tbl_Autores.Last;
    Cod1 := DM.Tbl_AutoresCodigo.AsInteger;
    Cod2 := Cod1 + 1;
    Edit_Codigo.Text := IntToStr(Cod2);

    //--------------------------------------
end;



tabela
-------
CREATE TABLE AUTORES (

    CODIGOINTEGER NOT NULL,
    AUTOR       VARCHAR(90) NOT NULL,
    
    CONSTRAINT PK_AUTORES PRIMARY KEY (CODIGO)
);



Mahdak

Mahdak

Curtidas 0

Respostas

Rjun

Rjun

31/08/2005

Faça um select que retorno o maior valor do campo código.

SELECT MAX(Codigo) FROM Autores



GOSTEI 0
Mahdak

Mahdak

31/08/2005

Faça um select que retorno o maior valor do campo código.
SELECT MAX(Codigo) FROM Autores


Rjun, fiz o seguinte com a sua dica, mas nao deu certo nao. ele só funcionou para adicionar o primeiro registro, mas para o segundo em diante nao deu... simplesmente ele continua colocando o código 1...


DM.Tbl_Autores.SelectSQL.Clear;
    cod := DM.Tbl_Autores.SelectSQL.add(´SELECT MAX(Codigo) FROM Autores´);
    Edit_Codigo.Text := IntToStr(Cod+1);




o que faço????


GOSTEI 0
Rjun

Rjun

31/08/2005

Não entendi muito bem o que você fez. Usa Query em vez de Table.

DM.qryProximoCodigo.SQL.Clear;
DM.qryProximoCodigo.SQL.add(´SELECT :NovoCodigo = MAX(Codigo) + 1 FROM Autores´); 
DM.qryProximoCodigo.Open;
try
  Edit_Codigo.Text := DM.qryProximoCodigo.ParamByName(´NovoCodigo´).AsString;
finally
  DM.qryProximoCodigo.Close;
end;



GOSTEI 0
Michelli88

Michelli88

31/08/2005

Nao deu certo porque isso:

cod := DM.Tbl_Autores.SelectSQL.add(´SELECT MAX(Codigo) FROM Autores´);

Vai retornar quantos registros foram alterados, e nao o codigo!

faz assim:
Query.SelectSQL.add(´SELECT MAX(Codigo) as ultimoCodigo FROM Autores´);

cod := Query.fieldbyname(´ultimoCodigo´).AsInteger;

;-)


GOSTEI 0
Gandalf.nho

Gandalf.nho

31/08/2005

Qual é o banco de dados?


GOSTEI 0
Mahdak

Mahdak

31/08/2005

Não entendi muito bem o que você fez. Usa Query em vez de Table.
DM.qryProximoCodigo.SQL.Clear;
DM.qryProximoCodigo.SQL.add(´SELECT :NovoCodigo = MAX(Codigo) + 1 FROM Autores´); 
DM.qryProximoCodigo.Open;
try
  Edit_Codigo.Text := DM.qryProximoCodigo.ParamByName(´NovoCodigo´).AsString;
finally
  DM.qryProximoCodigo.Close;
end;


- Seguinte, o Banco de dados é FireBird 1.5 extensão .FDB
Rjun, esse seu código retornou o seguinte erro:

´SQL error, line1, char 10 = ´, ou seja algum problema com o sinal de igualdade?


// Contador de Código
    DM.qry_autores.SelectSQL.Clear;
    DM.qry_autores.SelectSQL.add(´SELECT :NovoCodigo = MAX(Codigo) + 1 FROM Autores´);
    DM.qry_autores.Open;
    try
      Edit_Codigo.Text := DM.qry_autores.ParamByName(´NovoCodigo´).AsString;
    finally
      DM.qry_autores.Close;
    end;



GOSTEI 0
Motta

Motta

31/08/2005

Faça um select que retorno o maior valor do campo código.
SELECT MAX(Codigo) FROM Autores



SELECT (MAX(CODIGO) + 1 ) PROX
FROM TABELA

EXISTINDO VALOR !!


GOSTEI 0
Mahdak

Mahdak

31/08/2005

[quote:16881a8d7e=´Rjun´]Faça um select que retorno o maior valor do campo código.
SELECT MAX(Codigo) FROM Autores



SELECT (MAX(CODIGO) + 1 ) PROX
FROM TABELA

EXISTINDO VALOR !![/quote:16881a8d7e]

coloquei o primeiro registro no banco manualmente e ele nao gerou o codigo 2... nao funcionou nao...

// Contador de Código
    DM.qry_autores.Open;
    DM.qry_autores.SelectSQL.Clear;
    COD := DM.qry_autores.SelectSQL.add(´SELECT (MAX(CODIGO) + 1 ) PROX FROM AUTORES ´);
    DM.qry_autores.Close;


    Edit_Codigo.Text := IntToStr(cod);



GOSTEI 0
Motta

Motta

31/08/2005

// Contador de Código
DM.qry_autores.Open;
DM.qry_autores.SelectSQL.Clear;
DM.qry_autores.SQL.add(´SELECT (MAX(CODIGO) + 1 ) PROX FROM AUTORES ´);
dm.qry_autores.open;
cod := dm.qry_autores.fields[0].AsInteger;
DM.qry_autores.Close;


Edit_Codigo.Text := IntToStr(cod);


GOSTEI 0
Gandalf.nho

Gandalf.nho

31/08/2005

Se seu banco é Firebird, pq não usa generator?


GOSTEI 0
Mahdak

Mahdak

31/08/2005

// Contador de Código DM.qry_autores.Open; DM.qry_autores.SelectSQL.Clear; DM.qry_autores.SQL.add(´SELECT (MAX(CODIGO) + 1 ) PROX FROM AUTORES ´); dm.qry_autores.open; cod := dm.qry_autores.fields[0].AsInteger; DM.qry_autores.Close; Edit_Codigo.Text := IntToStr(cod);



Motta, deu certo, porem sómente quando ja tenho um valor inicial, por que quando a tabela esta vazia esse codigo retorna NULL e nao envia o numero 1 para o primeiro registro da tabela quando vou inserir o mesmo...


GOSTEI 0
Mahdak

Mahdak

31/08/2005

Se seu banco é Firebird, pq não usa generator?


Gandalf, voce poderia me dar um exemplo de Generator? ouvi falar que é muito bom....

Abraços!


GOSTEI 0
Mahdak

Mahdak

31/08/2005

[quote:7b8460153d=´gandalf.nho´]Se seu banco é Firebird, pq não usa generator?


Gandalf, voce poderia me dar um exemplo de Generator? ouvi falar que é muito bom....

Abraços![/quote:7b8460153d]


nesse curto espaço de tempo consegui atravez das pesquisas aqui no clube que posso criar o generator automaticamente pelo IBExpress, e depois linkar ele com o meu IBDataSet.. até ai ja consegui, mas agora eu tenho um botão ´novo´ em minha aplicação onde ele pega o numero a ser gerado no meu GenId e coloca em um edit pra eu ver... que codigo eu teria que uso pra fazer isso funcionar???
veja se esse raciocinio está correto:
DM.qry_autcod.Close;
    DM.qry_autores.SelectSQL.Clear;
    cod := DM.qry_autores.SelectSQL.add(´select gen_id(GEN_AUTORES_ID, 1) from rdb$database´);
    DM.qry_autores.Open;


    Edit_Codigo.Text := IntToStr(cod);




GOSTEI 0
Michelli88

Michelli88

31/08/2005

La no IBDataset, tem a propriedade GeneratorField voce vai ter ligar o GenId e o campo que vai receber os codigos gerados!


GOSTEI 0
Mahdak

Mahdak

31/08/2005

Pessoal, nao gostei muito do GenID, por que ele incrementa o codigo, e nao decrementa caso eu cancele a operação... seria perigoso em um sistema multi usuarios criar uma rotina de decrementação do código... entao resolvi juntar as ideias lá do clube... resolvi ficar com essa:

procedure TAutores.Btn_NovoClick(Sender: TObject);
var
Cod : Integer;
begin
    

    // Contador de Código 
    DM.qry_autcod.Open;
    DM.qry_autcod.SelectSQL.Clear;
    DM.qry_autcod.SelectSQL.add(´SELECT (MAX(CODIGO) + 1 ) PROX FROM AUTORES ´);
    dm.qry_autcod.open;
    cod := dm.qry_autcod.fields[0].AsInteger;
    DM.qry_autcod.Close;
    
    Edit_Codigo.Text := IntToStr(cod);
end;



Ela da certo, porem sómente quando ja tenho um valor inicial, por que quando a tabela esta vazia esse codigo retorna NULL e nao envia o numero 1 para o primeiro registro da tabela quando vou inserir o mesmo...
Voce nao saberia me dizer como posso fazer uma verificação, caso a tabela esteja vazia (NULL) entao gera o primeiro código?


GOSTEI 0
Gandalf.nho

Gandalf.nho

31/08/2005

Só uma pergunta, é obrigatório vc não ter buracos na sua numeração (como notas fiscais e similares)? Se não, use generator mesmo que é muito mais simples e garante que não haverá dois números iguais.


GOSTEI 0
Mahdak

Mahdak

31/08/2005

Só uma pergunta, é obrigatório vc não ter buracos na sua numeração (como notas fiscais e similares)? Se não, use generator mesmo que é muito mais simples e garante que não haverá dois números iguais.


Gandalf, nao posso ter furos por que gero etiquetas sequenciais, entao se houver furos na numeração haverá disperdicio de etiquetas.... caso contrario tambem achei o Generator bem interessante e muito mais funcional e facil de usar, porem acho que esse nao seria o meu caso...
o que vc acha?


GOSTEI 0
POSTAR