Fórum Trigger para campo autoincremento #50439
11/04/2005
0
Create Generator Inc_CodigoPaciente;
Set Generator Inc_Codigopaciente to 8681;
Set term ^ ;
Create Trigger CadPacientesAudmed_BI for CadPacientesAudmed
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
New.Codigo = Gen_id( Inc_CodigoPaciente, 1 );
END ^
As linhas acima eu criei pro firebird 1.5.1, setei o generator nessa posição pois antes eu criava os incrementos na mão, esse código 8681 é a ultima inserção que eu tenho no sistema, que está operando em estrutura cliente/servidor e vi a necessidade de criar uma trigger com autoincremento por questões de concorrência, mas ao testar no sistema, não consegui fazer as devidas configurações para recuperar esse codigo gerado automaticamente....
Uso dbexpress/clientdataset....
Quando dou
ClientDataSet.Insert
Abre para nova inserção, mas ao invés de pegar o codigo novo e limpar os campos para nova inserção, pela trigger, ele para no ultimo registro cadastrado e se dou cancelar, ele dá um erro, que não existe transação ativa...
ai já sei que estou errando pois não estou conseguindo pegar o novo código, pois é codigo de visualização e preciso mostrar na tela
Gostaria de uma ajuda , que vcs me explicassem o que estou fazendo e entendendo de errado, essa trigger não era pra ser ativada no momento que dou um ´Insert´ no ClientDataSet?? pois é isso que eu entendo com essa linha ´ACTIVE BEFORE INSERT´... ou ela só ativa depois que dou um ´ApplyUpdates(-1)´, sendo que esse meu campo Codigo é INTEGER NOT NULL PRIMARY KEY...
E onde tenho que configurar no sistema??? no SQLDataSet?? no DataSetProvider?? ClientDataSet??
Agradeço muito e estou com bastante urgência
Carlos Maurício
Carlosmauriciormachado
Curtir tópico
+ 0Posts
11/04/2005
Vinicius2k
A Trigger só será disparada no momento da efetiva inserção do registro no lado do servidor, mais precisamente após o ApplyUpdates do CDS. A inserção no CDS está sendo feita em memória local (no lado do cliente). É por esta razão que vc não visualizará o valor do generator até que aplique o método AppyUpdates seguido do método Refresh (ou Close/Open) no CDS.
Vc precisa ainda setar a propriedade ´Required´ do TField do ´CODIGOPACIENTE´ para ´False´ tanto no SQLDataSet quanto no ClientDataSet se a geração for feita pela Trigger.
Se vc precisa exibir o valor do generator para o usuário no momento da inserção local, precisa recuperar este valor através de uma query auxiliar com a instrução :
select GEN_ID(INC_CODIGOPACIENTE, 1) from RDB$DATABASE
O valor retornado por esta query será o novo valor gerado e a incrementação no banco de dados já terá sido feita.
É bom ressaltar que uma vez utilizada a instrução acima, mesmo que o usuário cancele a inserção, o valor estará ´perdido´ e não será re-utilizado.
Neste caso, a Trigger não pode ser utilizada, ao contrário vc terá um duplo incremento. Vc deve ´dropar´ estra trigger ou adotar a seguinte instrução:
IF (New.Codigo IS NULL) THEN New.Codigo = Gen_id( Inc_CodigoPaciente, 1 );
Com isto, a Trigger pode continuar existindo, mas só será disparada para incrementação se a coluna não estiver recebendo um valor vindo da aplicação.
Sobre o erro de não haver transação ativa, não está relacionado ao incremento e pode estar ligado à forma como vc está trabalhando a abertura dos DataSets.
Lembre-se : quando utilizar TClientDataSets apenas eles devem ser abertos. Nunca abra ou feche dos SQLDataSet pois sua única função é atender às requisições no TDataSetProvider.
Também já vi este erro quando utilizado o driver da UIB. Vc o está utilizando ou está utilizando o driver nativo (dbexpint.dll)
Espero ter ajudado.
T+
Gostei + 0
11/04/2005
Carlosmauriciormachado
Valeu Vinicius, blz!!!! entendi!!! alias ja tinha feito uma pesquisa no forum, achei essa solução que vc propos.... mas pelo que eu entendi, ainda posso manter a minha trigger, acrescentando o if mas evitar valor duplicado certo?? E utlizando essas duas soluções em conjunto, vou conseguir trabalhar a questão de concorrência?? ou seja , vou conseguir trabalhar numa mesma tela em 2 maquinas diferente??
Seguinte sobre o triplo post, foi falha minha... pressa pra mandar a duvida hehehehe :oops:
Ah to usando o UIB em sistema de produção sem nenhum problema!!!
abraços
MSN: consultormachado2001@hotmail.com, add me para a gente conversar de delphi
Gostei + 0
11/04/2005
Vinicius2k
Isso. Particularmente, quando estou modelando e diagramando meus Bancos, se há uma auto-incremento, eu sempre utilizo as triggers com a condição do novo valor ser nulo ou não. Com isso, não me preocupo ainda como a aplicação irá lidar com isso. Durante o desenvolvimento da aplicação é que vou determinar aonde deixar que trigger faça o incremento e aonde utilizar ´manualmente´. Desta forma, não preciso alterar o projeto do Banco.
Sem problemas. Não houve advertência, apenas os colegas foram orientados a postar as respostas neste tópico.
Cuidado ! O driver da UIB ainda é instável ao passo que o nativo para IB da Borland ainda funciona 100¬ com o FB. Vc pode estar correndo um risco desnecessário.
Já que agora vc confirmou minhas suspeitas, 99¬ de chances do erro com as transações estarem sendo causados por ele. Eu já presenciei este problema em meus testes.
T+
Gostei + 0
11/04/2005
Carlosmauriciormachado
Estou pensando de final de semana contribuir mais ativamente nos foruns!!! pois programar delphi eu adoro!!!
Abraços delphianos
Gostei + 0
18/04/2005
Carlosmauriciormachado
Abraços
Aguardo resposta
Gostei + 0
19/04/2005
Vinicius2k
Por enquanto sim (até o FB 1.5.x) ainda funciona 100¬. O maior problema é não ter a menor idéia de até quando esta compatibilidade vai se manter... pode ser que dure por muito tempo, ou pode ser que já no FB 2.0 comecem os ´problemas´...
Para serviços, eu prefiro criar interfaces com as aplicações console do próprio FB dentro da minha aplicação... por exemplo, o usuário informa os dados do Banco de dados, do arquivo de backup, marca ou desmarca algumas opções e no o ´executar´ ao invés de utilizar o IBBackupService a minha aplicação criará um processo com o próprio GBAK do FB.
T+
Gostei + 0
19/04/2005
Carlosmauriciormachado
Como vc faz para criar interfaces que usem esses tipos de servico no delphi??? nunca fiz?? tipo assim com o gbak do firebird??
É dificil???
Té +
Gostei + 0
19/04/2005
Vinicius2k
Um form com :
- 1 TEdit p/ caminho do banco de dados
- 1 TEdit p/ caminho do arquivo de backup
- 1 TEdit p/ informação do usuário do FB
- 1 TEdit p/ informação da senha do usuário do FB
- 1 TEdit p/ informar o caminho aonde se encontra o GBAK.
- 1 TButton com a ação para execução do backup.
Cria-se uma string para a linha de comando do GBAK baseada nos dados acima como :
CmdLine := ´c:\firebird\gbak.exe -b -v ´ + Edit1.text + ´ ´ + Edit2.Text + ´ -user ´ + Edit3.Text + ´ - pass ´ + Edit4.Text;
Criar um processo via API (CreateProcess) com a linha de comando para o GBAK como se vc estivesse executando no prompt.
Depois disso vc pode ´incrementar´, como utilizar algum componente de compactação e copiar o arquivo de backup compactado para uma mídia removível ou algo assim... Dar mais opções para ´marcar´ e ´desmarcar´ que representariam as opções que vc teria como se estivesse executando o GBAK via linha de comando... etc... etc...
Bastante simples e independente de compatibilidade com o IB.
T+
Gostei + 0
29/05/2008
Jessedelsole
Obrigado
Gostei + 0
29/05/2008
Joaoshi
CmdLine := ´c:\firebird\gbak.exe -b -v ´ + Edit1.text + ´ ´ + Edit2.Text + ´ -user ´ + Edit3.Text + ´ - pass ´ + Edit4.Text;
CmdLine := ´c:\firebird\gbak.exe -r -v ´ + Edit1.text + ´ ´ + Edit2.Text + ´ -user ´ + Edit3.Text + ´ - pass ´ + Edit4.Text;
Basicamente é isso.
Espero ter ajudado.
Gostei + 0
17/06/2008
Jessedelsole
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)