Trigger para campo autoincremento
Bom dia, pessoal... Aqui estou novamente depois de muito tempo e com uma duvida gigantesca:
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
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
Curtidas 0
Respostas
Vinicius2k
11/04/2005
Colega,
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 :
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:
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+
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
Carlosmauriciormachado
11/04/2005
:o
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
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
Vinicius2k
11/04/2005
...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??
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.
Seguinte sobre o triplo post, foi falha minha... pressa pra mandar a duvida hehehehe :oops:
Sem problemas. Não houve advertência, apenas os colegas foram orientados a postar as respostas neste tópico.
Ah to usando o UIB em sistema de produção sem nenhum problema!!!
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
Carlosmauriciormachado
11/04/2005
Valeu Vinicius2K, sua ajudinha foi providencial... hehhehe... Agora vou estudar mais umas coisinhas, daqui uns tempos volto pra torrar a paciencia da negada!!!! :shock: :twisted: Vc acha q devo investir em Stored Procedures??
Estou pensando de final de semana contribuir mais ativamente nos foruns!!! pois programar delphi eu adoro!!!
Abraços delphianos
Estou pensando de final de semana contribuir mais ativamente nos foruns!!! pois programar delphi eu adoro!!!
Abraços delphianos
GOSTEI 0
Carlosmauriciormachado
11/04/2005
Vinicius, Agora pensando, teve um ponto seu que me chamou aa atenção : ´compatibilidade com o driver dbexpress nativo do interbase´ .... Agora lanço outra pergunta, se eu usar os componentes da paleta ´Interbase Admin´ para validação/backup/restore, vai funcionar corretamente???
Abraços
Aguardo resposta
Abraços
Aguardo resposta
GOSTEI 0
Vinicius2k
11/04/2005
Olá !
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+
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
Carlosmauriciormachado
11/04/2005
Vinicius, Vou dar uma de curioso, hehehe :lol:
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é +
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
Vinicius2k
11/04/2005
Nada de difícil ! Extremamente simples, talvez até mais do que se usasse um componente... por exemplo :
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 :
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+
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
Jessedelsole
11/04/2005
olá Vinicius2K, qual seria o comando para realizar o ´restore dabase´ via código?
Obrigado
Obrigado
GOSTEI 0
Joaoshi
11/04/2005
Colega, substitua o -b por [b:ec3abe91dd]-r[/b:ec3abe91dd]
CmdLine := ´c:\firebird\gbak.exe -r -v ´ + Edit1.text + ´ ´ + Edit2.Text + ´ -user ´ + Edit3.Text + ´ - pass ´ + Edit4.Text;
Basicamente é isso.
Espero ter ajudado.
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
Jessedelsole
11/04/2005
mt obrigado! eu irei testar!
GOSTEI 0