Auto incremento
Olá amigos, boa noite
Preciso da ajuda de vocês com uma questão sobre autoincremento
A situação é a seguinte , criei um trigger para calcular o campo codcli e fazer seu autoincremento , segue p código da trigger e do generator:
Está funcionando PERFEITAMENTE, faz exatamente o que deveria. A minha dúvida é sobre o seguinte:
Imaginemos que eu tenha 10 registros na tabela e delete 3 deles, quando eu inserir um novo ele será o codcli 11 pois o generator está setado para 11, como fazer o generator verificar o maior valor do campo códcli e receber este valor para que ao rodar a trigger o codigo seja corretamente o valor 8?
Obrigado a todos desde já
Preciso da ajuda de vocês com uma questão sobre autoincremento
A situação é a seguinte , criei um trigger para calcular o campo codcli e fazer seu autoincremento , segue p código da trigger e do generator:
create generator inc_codcli;
create trigger tb_Cliente for cliente active before insert position 0 as begin if (new.codcli is null) then new.codcli = gen_id (inc_codcli,1); end
Está funcionando PERFEITAMENTE, faz exatamente o que deveria. A minha dúvida é sobre o seguinte:
Imaginemos que eu tenha 10 registros na tabela e delete 3 deles, quando eu inserir um novo ele será o codcli 11 pois o generator está setado para 11, como fazer o generator verificar o maior valor do campo códcli e receber este valor para que ao rodar a trigger o codigo seja corretamente o valor 8?
Obrigado a todos desde já
Zoom
Curtidas 0
Respostas
Emerson Nascimento
02/12/2006
crieo que nesse caso você não poderá trabalhar com generator´s. terá de fazer a coisa na mão:
assim o generator nem será necessário, podendo até ser ´dropado´
create trigger tb_Cliente for cliente active before insert position 0 as begin if (new.codcli is null) then new.codcli = (select coalesce(max(codcli),0)+1 from tb_Cliente); end
GOSTEI 0
Martins
02/12/2006
Desculpem eu meter minha colher aqui, pois sou um mero aprendiz professores, mas não corre o risco de gerar um código que já existe?
Tipo.
Tipo.
ID_CLI NOME_CLI 1 MARIA 2 JOAO 3 MARCOS 4 AURÉLIO 5 JONAS 6 THIAGO // Se eu deletar os três últimos registros e depois incrementar novamente vai dar certo, mas se eue deletar digamos (2, 4 e 5) eu terei ficado com 03 (três) registros não é isso, então incrementando novamente apartir do maior código existente que seria o 06 (seis) eu teria (7,...) não seria isso? Se não for assim, podem me explicar como funcionaria então, pq isso é interessante, não deixar brechas na sequencia númerica dos códigos. valew!!
GOSTEI 0
Emerson Nascimento
02/12/2006
Martins, da forma como eu passei esse risco não existe, porque a instrução trará o maior valor de registro acrescido de 1, então, se você excluiu os registros 2, 4 e 5, ainda assim o novo registro gerado seria o 7, pois seria o maior (6) acrescido de 1.
mas o que o Martins mostrou é um caso muito comum. Quando houver exclusão de registros intermediários, ficará, sim, uma ´brecha´ entre os registros.
e, pra falar a verdade, eu nunca entendi muito porque a preocupação com o ID gerado para os registros. ele deveria ter usado internamente, transparente ao usuário.
mas o que o Martins mostrou é um caso muito comum. Quando houver exclusão de registros intermediários, ficará, sim, uma ´brecha´ entre os registros.
e, pra falar a verdade, eu nunca entendi muito porque a preocupação com o ID gerado para os registros. ele deveria ter usado internamente, transparente ao usuário.
GOSTEI 0
Martins
02/12/2006
Martins, da forma como eu passei esse risco não existe, porque a instrução trará o maior valor de registro acrescido de 1, então, se você excluiu os registros 2, 4 e 5, ainda assim o novo registro gerado seria o 7, pois seria o maior (6) acrescido de 1.
mas o que o Martins mostrou é um caso muito comum. Quando houver exclusão de registros intermediários, ficará, sim, uma ´brecha´ entre os registros.
e, pra falar a verdade, eu nunca entendi muito porque a preocupação com o ID gerado para os registros. ele deveria ter usado internamente, transparente ao usuário.
Ok [b:126b8f3738]Emerson.en[/b:126b8f3738], entendi agora meu amigo e concordo com vc quanto ao ID.
valew
GOSTEI 0
Martins
02/12/2006
Martins, da forma como eu passei esse risco não existe, porque a instrução trará o maior valor de registro acrescido de 1, então, se você excluiu os registros 2, 4 e 5, ainda assim o novo registro gerado seria o 7, pois seria o maior (6) acrescido de 1.
mas o que o Martins mostrou é um caso muito comum. Quando houver exclusão de registros intermediários, ficará, sim, uma ´brecha´ entre os registros.
e, pra falar a verdade, eu nunca entendi muito porque a preocupação com o ID gerado para os registros. ele deveria ter usado internamente, transparente ao usuário.
Ok [b:089dc51585]Emerson.en[/b:089dc51585], entendi agora meu amigo e concordo com vc quanto ao ID.
valew
GOSTEI 0
Martins
02/12/2006
Martins, da forma como eu passei esse risco não existe, porque a instrução trará o maior valor de registro acrescido de 1, então, se você excluiu os registros 2, 4 e 5, ainda assim o novo registro gerado seria o 7, pois seria o maior (6) acrescido de 1.
mas o que o Martins mostrou é um caso muito comum. Quando houver exclusão de registros intermediários, ficará, sim, uma ´brecha´ entre os registros.
e, pra falar a verdade, eu nunca entendi muito porque a preocupação com o ID gerado para os registros. ele deveria ter usado internamente, transparente ao usuário.
Ok [b:d0c684b3ad]Emerson.en[/b:d0c684b3ad], entendi agora meu amigo e concordo com vc quanto ao ID.
valew
GOSTEI 0
Adriano_servitec
02/12/2006
Olah Emerson, tentei criar uma Trigger assim como vc postou no IBExpert, mais nao gera da erro de script
Nao pode criar esta nova trigger no before insert do ibexpert?
CREATE TRIGGER CORRENTE_BI0 FOR CORRENTE ACTIVE BEFORE INSERT POSITION 0 as begin if (new.sequencia2 is null) then new.sequencia2 = (select coalesce(max(sequencia2),0)+1 from CORRENTE_BI0); end
Nao pode criar esta nova trigger no before insert do ibexpert?
GOSTEI 0
Emerson Nascimento
02/12/2006
CREATE TRIGGER CORRENTE_BI0 FOR CORRENTE ACTIVE BEFORE INSERT POSITION 0 as begin if (new.sequencia2 is null) then new.sequencia2 = (select coalesce(max(sequencia2),0)+1 from CORRENTE); end
GOSTEI 0
Adriano_servitec
02/12/2006
Desculpe a percistencia Emerson, mais nao consegui fazer funcionar
Erro
Bom eu criei este campo chamado [b:0be7c4e944]sequencia2[/b:0be7c4e944] como integer e na aba trigger da tabela dentro do ibexpert no before insert usei a opçao [b:0be7c4e944]New Trigger[/b:0be7c4e944] e coloquei o script do SQL e depois na hora que clico em [b:0be7c4e944]compiler trriger[/b:0be7c4e944] gera o erro acima.
CREATE TRIGGER CORRENTE_BI0 FOR CORRENTE ACTIVE BEFORE INSERT POSITION 0 AS begin /* Trigger text */ if (new.sequencia2 is null) then new.sequencia2 = (select coalesce(max(sequencia2),0)+1 from CORRENTE); end
Erro
Column does not belong to referenced table.
Dynamic SQL Error.
SQL error code = -206.
Subselect illegal in this context.
Bom eu criei este campo chamado [b:0be7c4e944]sequencia2[/b:0be7c4e944] como integer e na aba trigger da tabela dentro do ibexpert no before insert usei a opçao [b:0be7c4e944]New Trigger[/b:0be7c4e944] e coloquei o script do SQL e depois na hora que clico em [b:0be7c4e944]compiler trriger[/b:0be7c4e944] gera o erro acima.
GOSTEI 0
Emerson Nascimento
02/12/2006
ops!!! realmente havia um erro... :oops:
tente assim:
tente assim:
CREATE TRIGGER CORRENTE_BI FOR CORRENTE ACTIVE BEFORE INSERT POSITION 0 AS DECLARE VARIABLE NOVASEQUENCIA INTEGER; BEGIN IF (NEW.SEQUENCIA2 IS NULL) THEN BEGIN SELECT COALESCE(MAX(SEQUENCIA2),0)+1 FROM CORRENTE INTO :NOVASEQUENCIA; NEW.SEQUENCIA2 = NOVASEQUENCIA; END END
GOSTEI 0
Adriano_servitec
02/12/2006
Descobri como eh o correto
AS begin /* Trigger text */ if (new.sequencia2 is null) then select coalesce(max(sequencia2),0)+1 from CORRENTE into new.sequencia2; end
GOSTEI 0
Adriano_servitec
02/12/2006
Olah Emerson, agora me surgiu uma duvida, eu postei se ter visto o teu post praticamente eh o mesmo codigo que eu postei com exeçao que foi declarada uma variavel [b:25fee2ed8d]DECLARE VARIABLE NOVASEQUENCIA INTEGER; [/b:25fee2ed8d]
Entao novamente a pergunta
O que eu fiz NAO esta correto?
Lembrando que nao conheço quase nada ainda de trigger
Entao novamente a pergunta
O que eu fiz NAO esta correto?
Lembrando que nao conheço quase nada ainda de trigger
GOSTEI 0
Emerson Nascimento
02/12/2006
o que você postou está correto.
é que eu tenho costume de trabalhar com variáveis, por conta de geralmente fazer mais de uma avaliação com o valor obtido.
é que eu tenho costume de trabalhar com variáveis, por conta de geralmente fazer mais de uma avaliação com o valor obtido.
GOSTEI 0
Adriano_servitec
02/12/2006
o que você postou está correto.
é que eu tenho costume de trabalhar com variáveis, por conta de geralmente fazer mais de uma avaliação com o valor obtido.
Valeu amigo, muito obrigado.
Andei fazendo uns testes aki
Bom primeiro zerei o banco de dados pois a sequencia estava pegado o ultimo do generator, ai fiz uns lançamentos com a nova trriger e ficou na sequencia
1
2
3
ai exclui a sequenca 2
e fiz outro lançamento e ficou assim
1
3
4
a pergunta eh teria como voltar a ficar assim
1
2
3
em vez de
1
3
4
Ou no caso tem algum problema em fazer um retocesso na trigger pois no caso ai o que eh sequencia 3 passa a ser sequencia 2. Nao sei se pode fazer isso sem afetar o banco.
Lembrando que esse campo nao eh nem chave primaria nem chave estrangeira, uso apenas para fazer alguns updates e delete por ele.
GOSTEI 0
Emerson Nascimento
02/12/2006
tem sim. faça uma trigger after delete:
obs.:para tornar a execução mais rápida - tanto dessa trigger quanto da anterior - crie um índice pelo campo sequencia2
CREATE TRIGGER CORRENTE_DEL FOR CORRENTE ACTIVE AFTER DELETE POSITION 0 AS BEGIN UPDATE CORRENTE SET SEQUENCIA2 = SEQUENCIA2 - 1 WHERE SEQUENCIA2 > OLD.SEQUENCIA2; END
obs.:para tornar a execução mais rápida - tanto dessa trigger quanto da anterior - crie um índice pelo campo sequencia2
GOSTEI 0
Adriano_servitec
02/12/2006
tem sim. faça uma trigger after delete:
obs.:para tornar a execução mais rápida - tanto dessa trigger quanto da anterior - crie um índice pelo campo sequencia2
CREATE TRIGGER CORRENTE_DEL FOR CORRENTE ACTIVE AFTER DELETE POSITION 0 AS BEGIN UPDATE CORRENTE SET SEQUENCIA2 = SEQUENCIA2 - 1 WHERE SEQUENCIA2 > OLD.SEQUENCIA2; END
Olah Emerson, testei aqui e desta forma deleta todos os registros posteriores tipo se eu tiver assim
1
2
3
e deletar a sequencia 2
fica soh o 1
ou seja deleta o 2 e o 3 e assim por diante
eu uso para deletar assim
if edit4.Text = ´´ then begin raise Exception.Create(´É necessário selecionar a Linha na Grade para Excluir´); end else if application.messagebox(Pchar(´Deseja Excluir este Lançamento:´ + #13+ dm.qrylimpa.FieldByName(´Sequencia´).AsString +´ ´+ 13+ dm.qrylimpa.FieldByName(´associado´).AsString), Pchar(´Excluir Dados´+Self.Caption), MB_ICONQUESTION + MB_YESNO) = IDYES then begin with dm.qrylimpa do begin Close; SQL.Clear; sql.text := ´delete from corrente where sequencia = :vExclui´; ParamByName(´vExclui´).Value :=vExclui; try ExecSQL; dm.tlimpa.commit; dm.qrylimpa.close; dm.qrylimpa.sql.clear; dm.qrylimpa.sql.text := ´select * from corrente where matricula = :matricula´; dm.qrylimpa.Open; sbar.SimpleText := ´Linha Excluída...´; except On E:Exception do begin dm.ibt2.Rollback; dm.tlimpa.Rollback; sbar.SimpleText := ´Abortado...´; Showmessage(´Falha na Exclusão dos Dados!´#1310´Mensagem: ´+E.Message); end; end; end; end;
como uso o dbgrid para excluir fiz este codigo aqui tambem
procedure TForm6.DBGrid1CellClick(Column: TColumn); begin vexclui:=dm.qrylimpa.fieldbyname(´sequencia´).asinteger; edit4.text:=inttostr(vExclui); end;
Outra coisa amigo, como crio indice neste campo SEQUENCIA2
Obrigado mais uma vez por me ajudar.
GOSTEI 0
Emerson Nascimento
02/12/2006
[quote:b6f2def0a7=´emerson.en´]tem sim. faça uma trigger after delete:
obs.:para tornar a execução mais rápida - tanto dessa trigger quanto da anterior - crie um índice pelo campo sequencia2
CREATE TRIGGER CORRENTE_DEL FOR CORRENTE ACTIVE AFTER DELETE POSITION 0 AS BEGIN UPDATE CORRENTE SET SEQUENCIA2 = SEQUENCIA2 - 1 WHERE SEQUENCIA2 > OLD.SEQUENCIA2; END
Olah Emerson, testei aqui e desta forma deleta todos os registros posteriores tipo se eu tiver assim
1
2
3
e deletar a sequencia 2
fica soh o 1
ou seja deleta o 2 e o 3 e assim por diante
eu uso para deletar assim
if edit4.Text = ´´ then begin raise Exception.Create(´É necessário selecionar a Linha na Grade para Excluir´); end else if application.messagebox(Pchar(´Deseja Excluir este Lançamento:´ + #13+ dm.qrylimpa.FieldByName(´Sequencia´).AsString +´ ´+ 13+ dm.qrylimpa.FieldByName(´associado´).AsString), Pchar(´Excluir Dados´+Self.Caption), MB_ICONQUESTION + MB_YESNO) = IDYES then begin with dm.qrylimpa do begin Close; SQL.Clear; sql.text := ´delete from corrente where sequencia = :vExclui´; ParamByName(´vExclui´).Value :=vExclui; try ExecSQL; dm.tlimpa.commit; dm.qrylimpa.close; dm.qrylimpa.sql.clear; dm.qrylimpa.sql.text := ´select * from corrente where matricula = :matricula´; dm.qrylimpa.Open; sbar.SimpleText := ´Linha Excluída...´; except On E:Exception do begin dm.ibt2.Rollback; dm.tlimpa.Rollback; sbar.SimpleText := ´Abortado...´; Showmessage(´Falha na Exclusão dos Dados!´#1310´Mensagem: ´+E.Message); end; end; end; end;
como uso o dbgrid para excluir fiz este codigo aqui tambem
procedure TForm6.DBGrid1CellClick(Column: TColumn); begin vexclui:=dm.qrylimpa.fieldbyname(´sequencia´).asinteger; edit4.text:=inttostr(vExclui); end;
Outra coisa amigo, como crio indice neste campo SEQUENCIA2
Obrigado mais uma vez por me ajudar.[/quote:b6f2def0a7]
não procede. o código que eu te passei não apaga nada. simplesmente atualiza os registros.
uma dica: as linhas onde há sql.clear são totalmente desnecessárias no seu código.
veja se a exclusão não de dá por outro motivo.
GOSTEI 0
Adriano_servitec
02/12/2006
Nada, nao cosegui ainda
Eu chegue ateh a mudar o where pra ver se dava certo, ai fiz assim
AS
begin
/* Trigger text */
UPDATE CORRENTE SET SEQUENCIA = SEQUENCIA - 1
WHERE SEQUENCIA <> OLD.SEQUENCIA;
end
Estava assim
1
2
3
4
deletei o 3
Nesta forma ficou assim
-1
0
Ainda nao consegui fazer o certo
Eu chegue ateh a mudar o where pra ver se dava certo, ai fiz assim
AS
begin
/* Trigger text */
UPDATE CORRENTE SET SEQUENCIA = SEQUENCIA - 1
WHERE SEQUENCIA <> OLD.SEQUENCIA;
end
Estava assim
1
2
3
4
deletei o 3
Nesta forma ficou assim
-1
0
Ainda nao consegui fazer o certo
GOSTEI 0
Emerson Nascimento
02/12/2006
sequencia? não era sequencia2 ?!?!?!?!? o campo sequencia não poderá ser usado, pois é nele que você se baseia para fazer a exclusão do registro (usado no where). dessa forma, o mecanismo do banco de dados ´se perde´.
tente colocar mais um campo na sua instrução de exclusão.
delete from corrente where sequencia = :vExclui and [qualquer outra condição]
tente colocar mais um campo na sua instrução de exclusão.
delete from corrente where sequencia = :vExclui and [qualquer outra condição]
GOSTEI 0
Adriano_servitec
02/12/2006
sequencia? não era sequencia2 ?!?!?!?!? o campo sequencia não poderá ser usado, pois é nele que você se baseia para fazer a exclusão do registro (usado no where). dessa forma, o mecanismo do banco de dados ´se perde´.
tente colocar mais um campo na sua instrução de exclusão.
delete from corrente where sequencia = :vExclui and [qualquer outra condição]
Entao nao pode ser o campo sequencia? Eu tinha criado o campo sequencia2, mais como me baseio pelo campo sequenca acehi melhor usar as trigger criadas acima no campo sequencia da tabela corrente.
tente colocar mais um campo na sua instrução de exclusão.
delete from corrente where sequencia = :vExclui and [qualquer outra condição]
O que vc sujere aqui (nao entendi o que mais devo colocar na condiçao do where), isto eh se tiver como usar o campo sequencia para atualizar a tabela usando o update.GOSTEI 0
Adriano_servitec
02/12/2006
Esqueçe tudo amigo, ja foi resolvido o problema, eu continuei insistindo no sequencia que eh o campo que serve de base para tudo.
Lembra la no começo que tu me disse assim:
No mais soh faltava isso mesmo, por isso que estava bagunçando o trigger :D
Do mais os codigos acima sao os mesmo que vc me passou soh com a mudança dos campos sequenca2 para sequencia.
Bom amigo, agora sim esta como eu queria. 100¬ perfeito
Mais uma vez agradeço sua paciencia e ajuda nesta duvida.
Pra mim caso encerrado, soh nao sei pro amigo dono do post que postou a duvida. :?:
Me desculpe por ter invadido o teu post com minhas duvidas. :oops:
Valeu ai Emerson
Lembra la no começo que tu me disse assim:
obs.:para tornar a execução mais rápida - tanto dessa trigger quanto da anterior - crie um índice pelo campo sequencia2
Pois eh nao sabia como ia criar este indices, ai lendo uma apostila descobri como criar o indice,ae criei um indice chamado [b:7202feb583]CORRENTE_IDX1[/b:7202feb583] e coloquei o campo sequencia como indice.No mais soh faltava isso mesmo, por isso que estava bagunçando o trigger :D
Do mais os codigos acima sao os mesmo que vc me passou soh com a mudança dos campos sequenca2 para sequencia.
Bom amigo, agora sim esta como eu queria. 100¬ perfeito
Mais uma vez agradeço sua paciencia e ajuda nesta duvida.
Pra mim caso encerrado, soh nao sei pro amigo dono do post que postou a duvida. :?:
Me desculpe por ter invadido o teu post com minhas duvidas. :oops:
Valeu ai Emerson
GOSTEI 0