Fórum Trigger para campo autoincremento #50439

11/04/2005

0

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


Carlosmauriciormachado

Carlosmauriciormachado

Responder

Posts

11/04/2005

Vinicius2k

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 :
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+


Responder

Gostei + 0

11/04/2005

Carlosmauriciormachado

: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


Responder

Gostei + 0

11/04/2005

Vinicius2k

...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+


Responder

Gostei + 0

11/04/2005

Carlosmauriciormachado

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


Responder

Gostei + 0

18/04/2005

Carlosmauriciormachado

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


Responder

Gostei + 0

19/04/2005

Vinicius2k

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+


Responder

Gostei + 0

19/04/2005

Carlosmauriciormachado

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é +


Responder

Gostei + 0

19/04/2005

Vinicius2k

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 :
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+


Responder

Gostei + 0

29/05/2008

Jessedelsole

olá Vinicius2K, qual seria o comando para realizar o ´restore dabase´ via código?
Obrigado


Responder

Gostei + 0

29/05/2008

Joaoshi

Colega, substitua o -b por [b:ec3abe91dd]-r[/b:ec3abe91dd]
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.


Responder

Gostei + 0

17/06/2008

Jessedelsole

mt obrigado! eu irei testar!


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar