Exibir codigo após applyupdate
Oi pessoal,
estou usando o D7 com DBExpress e Firebird e tenho a seguinte SQL no SQLDataset:
SELECT * FROM CLIENTES WHERE CODIGO = :CODIGO
a tabela CLIENTES tem o campo CODIGO q é autonumeração
tudo está funcionando perfeitamente só q quando mando gravar, o código não é mostrado no dbtext, e se dou um refresh, devido ao parametro não é exibido nenhum registro.
quando não trabalho com parametro, posso usar o bookmark, mas, assim, não sei como fazer.
alguém pode me dar uma dica?
estou usando o D7 com DBExpress e Firebird e tenho a seguinte SQL no SQLDataset:
SELECT * FROM CLIENTES WHERE CODIGO = :CODIGO
a tabela CLIENTES tem o campo CODIGO q é autonumeração
tudo está funcionando perfeitamente só q quando mando gravar, o código não é mostrado no dbtext, e se dou um refresh, devido ao parametro não é exibido nenhum registro.
quando não trabalho com parametro, posso usar o bookmark, mas, assim, não sei como fazer.
alguém pode me dar uma dica?
Fajo
Curtidas 0
Respostas
.lg.
08/07/2009
Teria como você postar o codigo de sua unit para facilitar a ajuda!? Se for muito grande.. (500, 1000, 2000 linhas) poste somente o código do seu post.
Ahh... lembre-se de postar os SELECTs que vc tá usando para a inserção.
Ps.:´Por favor use [b:af225b1962][[/b:af225b1962][b:af225b1962]Code[/b:af225b1962][b:af225b1962]]...seu codigo....[[/b:af225b1962][b:af225b1962]/Code[/b:af225b1962][b:af225b1962]][/b:af225b1962]´
Ahh... lembre-se de postar os SELECTs que vc tá usando para a inserção.
Ps.:´Por favor use [b:af225b1962][[/b:af225b1962][b:af225b1962]Code[/b:af225b1962][b:af225b1962]]...seu codigo....[[/b:af225b1962][b:af225b1962]/Code[/b:af225b1962][b:af225b1962]][/b:af225b1962]´
GOSTEI 0
Fajo
08/07/2009
.lg. cara é seguinte, tenho um form q representa a tabela de cadastro de clientes, com um dbnavigator e um botão com o código tbclientes.Applyupdate(0);
a query contem a seguinte SQL:
SELECT * FROM CLIENTES WHERE CODIGO = :CODIGO
ou seja, só vai abrir um registro por vez.
no form tenho:
um dbtext para o campo codigo
um dbedit para o campo nome
quando clico no botão gravar ele grava normalmente, só q o código, q é gerado automaticment pelo banco não aparece imediatamente, e eu gostaria de saber como fazer para q ele seja exibido assim q clicar no botão gravar.
a query contem a seguinte SQL:
SELECT * FROM CLIENTES WHERE CODIGO = :CODIGO
ou seja, só vai abrir um registro por vez.
no form tenho:
um dbtext para o campo codigo
um dbedit para o campo nome
quando clico no botão gravar ele grava normalmente, só q o código, q é gerado automaticment pelo banco não aparece imediatamente, e eu gostaria de saber como fazer para q ele seja exibido assim q clicar no botão gravar.
GOSTEI 0
Marcos.gandin
08/07/2009
O que você pode fazer é buscar o último código inserido e mostrar no campo código com o select abaixo:
SELECT MAX(CODIGO) AS CODIGO FROM CLIENTES
Ou seja, você grava o código e já em seguida busca o maior código inserido, que vai ser o código gerado e mostra no campo código.
SELECT MAX(CODIGO) AS CODIGO FROM CLIENTES
Ou seja, você grava o código e já em seguida busca o maior código inserido, que vai ser o código gerado e mostra no campo código.
GOSTEI 0
Fajo
08/07/2009
Mas marcos essa forma eu já uso quando escolho q o código seja gerada no próprio delphi, o problema está exatamente pq o código está sendo gerado no banco, é claro q se não encontrar uma solução, terei q desativar a autonumeração do banco e passar a utilizar essa solução, mas não é possível q não haja uma solução plausível para esse problema.
GOSTEI 0
Marcos.gandin
08/07/2009
Mas pelo que entendi o código é gerado automaticamente e não através da query: SELECT MAX(CODIGO) + 1 FROM CLIENTES
Se for assim, por essa query é só mostrar o código gerado. O que eu sugeri foi:
SELECT MAX(CODIGO) AS CODIGO FROM CLIENTES
sem o +1.
Você pode continuar a usar a autonumeração sem problemas, só vai usar essa query pra pegar o código gerado e mostrar na tela.
Se for assim, por essa query é só mostrar o código gerado. O que eu sugeri foi:
SELECT MAX(CODIGO) AS CODIGO FROM CLIENTES
sem o +1.
Você pode continuar a usar a autonumeração sem problemas, só vai usar essa query pra pegar o código gerado e mostrar na tela.
GOSTEI 0
Fajo
08/07/2009
Ok, entendi,
agora se o sistema estiver em rede, e tiver sendo feito 2 cadastros de clientes ao mesmo tempo em estações diferentes..., acho q não vai dar sempre certo.
agora se o sistema estiver em rede, e tiver sendo feito 2 cadastros de clientes ao mesmo tempo em estações diferentes..., acho q não vai dar sempre certo.
GOSTEI 0
Lightshine
08/07/2009
Em que momento vc cria o código autonumeração? (antes de inserir, depois de inserir, antes de salvar...)
Uma ideia séria após criar o código vc salvar ele numa variavel, e após salvar as alterações fazer uma pesquisa pelo codigo que vc salvou na variavel e retornar os dados na tela.
Deu pra entender ou fui mto confusa?? rs
Lightshine
Uma ideia séria após criar o código vc salvar ele numa variavel, e após salvar as alterações fazer uma pesquisa pelo codigo que vc salvou na variavel e retornar os dados na tela.
Deu pra entender ou fui mto confusa?? rs
Lightshine
GOSTEI 0
Danielrsanches
08/07/2009
Ok, entendi,
agora se o sistema estiver em rede, e tiver sendo feito 2 cadastros de clientes ao mesmo tempo em estações diferentes..., acho q não vai dar sempre certo.
olá fajo !!!
olha, eu tenho o mesmo problema que o seu, mas pelo jeito, é um negócio meio sem solução (pelo menos até hj não consegui resolver 100¬)...
a única coisa que fiz, foi fazer o que o nosso amigo marcos.gandin falou:
O que você pode fazer é buscar o último código inserido e mostrar no campo código com o select abaixo:
SELECT MAX(CODIGO) AS CODIGO FROM CLIENTES
Ou seja, você grava o código e já em seguida busca o maior código inserido, que vai ser o código gerado e mostra no campo código.
quanto ao que vc disse, e tem toda razão:
agora se o sistema estiver em rede, e tiver sendo feito 2 cadastros de clientes ao mesmo tempo em estações diferentes..., acho q não vai dar sempre certo.
uma solução, é vc gerar o código apenas na hora de salvar o registro. o único problema, é que vc não conseguirá exibir o código ao usuário enquanto vc insere o registro, sendo possível apenas após salvá-lo ...
outra solução, é, assim que vc for inserir um novo registro, vc gravá-lo e entrar em modo de edição... assim vc já estará com o código na mão... só terá que se atentar em excluir o registro caso o usuário cancela a inclusão ...
espero ter conseguido explicar minha idéia !!!
abraços !!!
GOSTEI 0
Fajo
08/07/2009
Resultado:
se for pra exibir o código após o salvamento do registro, não deixe o banco responsável pela numeração do campo, faça pelo próprio Delphi.
se for pra exibir o código após o salvamento do registro, não deixe o banco responsável pela numeração do campo, faça pelo próprio Delphi.
GOSTEI 0
Discorpio
08/07/2009
Boa noite a todos.
Uma coisa que vocês precisam saber sobre DBExpress é que o método ApplyUpdates do componente TClientDataSet por si só não grava no banco físico. O que ApplyUpdate faz é criar um conjunto de registros em lote com as linhas inseridas e ou editadas chamado de Delta. O dados só serão gravados no banco físico após o acionamento do método Commit do TSQLConnection, pois o Commit faz o TDataSetProvider apanhar os dados no Delta e fazer a atualização linha a linha.
Outra coisa é que o DBExpress trabalha com registros desconectados, ou seja, os componentes unidirecionais que são TSQLDataSet, TSQLTable e o TSQuery e até mesmo o TSQLStoredProc, apanham os registros no banco físico de dados através de uma transação e os enviam para o TDataSetProvider que monta o cursor de dados no TClientDataSet fazendo um cache local no HD, e despois fecha a transação se desconectando do banco.
Assim sendo, para fazer o que você pretende, ou seja, a autoincremento tem que se mesmo na aplicação Delphi, e não no banco, e este auto-incremento tem que ser realizado de preferência no momento da Inserção de dados no cache local do hd, ou seja, no TClientDataSet.
Mas como vou saber qual o último registro, se ele está lá no banco físico :?:
Simples, voce vai usar um componente TSQLQuery somente linkado ao TSQLConnection, não link ele com nenhum TDataSetProvider e nem TClienteDataSet, apenas para apanhar o código do último registro e somar mais um, e com a instrução SQL da dica do nosso amigo Marcos.Gandin, só que desta forma:
Repare que dentro do SQL eu já faço o autoincremento.
Como o TSQLQuery abre a transação, apanha o último código e já o incrementa, isto significa dizer que este autoincremento já está dentro da sua aplicação, bastando tão somente associar ele a campo Codigo no TClientDataSet, tudo isso sendo feito no momento de inserção do registro no TClientDataSet, no evento OnNewRecord, assim:
Assim eu mato dois coelhos com um cajadada só, ou seja, vou a banco de dados, apanho o último registro e o incremento, associo o valor ao campo código do ClientDataSet no momento da Inserção de dados, quando faço isso, qualquer componente que liga a dados que estiver linkado a ClientDataSet e o campo código, ele ficará visível, voce fica sabendo qual o último registro já no momento da Inserção de dados no ClientDataSet.
A outra cajada é que se eu cancelar a inserção de registro, esse autoincremento não será enviada ao banco físico, que repito mais uma vez, só será possível com o acionamento do método Commit do SQLConnection.
Uma coisa que vocês precisam saber sobre DBExpress é que o método ApplyUpdates do componente TClientDataSet por si só não grava no banco físico. O que ApplyUpdate faz é criar um conjunto de registros em lote com as linhas inseridas e ou editadas chamado de Delta. O dados só serão gravados no banco físico após o acionamento do método Commit do TSQLConnection, pois o Commit faz o TDataSetProvider apanhar os dados no Delta e fazer a atualização linha a linha.
Outra coisa é que o DBExpress trabalha com registros desconectados, ou seja, os componentes unidirecionais que são TSQLDataSet, TSQLTable e o TSQuery e até mesmo o TSQLStoredProc, apanham os registros no banco físico de dados através de uma transação e os enviam para o TDataSetProvider que monta o cursor de dados no TClientDataSet fazendo um cache local no HD, e despois fecha a transação se desconectando do banco.
Assim sendo, para fazer o que você pretende, ou seja, a autoincremento tem que se mesmo na aplicação Delphi, e não no banco, e este auto-incremento tem que ser realizado de preferência no momento da Inserção de dados no cache local do hd, ou seja, no TClientDataSet.
Mas como vou saber qual o último registro, se ele está lá no banco físico :?:
Simples, voce vai usar um componente TSQLQuery somente linkado ao TSQLConnection, não link ele com nenhum TDataSetProvider e nem TClienteDataSet, apenas para apanhar o código do último registro e somar mais um, e com a instrução SQL da dica do nosso amigo Marcos.Gandin, só que desta forma:
Select (Max(Codigo) + 1) as Ultimo From Clientes
Repare que dentro do SQL eu já faço o autoincremento.
Como o TSQLQuery abre a transação, apanha o último código e já o incrementa, isto significa dizer que este autoincremento já está dentro da sua aplicação, bastando tão somente associar ele a campo Codigo no TClientDataSet, tudo isso sendo feito no momento de inserção do registro no TClientDataSet, no evento OnNewRecord, assim:
procedure TForm1.ClientDataSet1NewRecord(DataSet: TDataSet); begin SQLQuery1.Open; if SQLQueryUltimo.isNull then ClientDataSet1Codigo.asInteger := 1 else ClientDataSet1Codigo.asInteger := SQLQuery1Utimo.asInteger; SQLQuery1.Close; end;
Assim eu mato dois coelhos com um cajadada só, ou seja, vou a banco de dados, apanho o último registro e o incremento, associo o valor ao campo código do ClientDataSet no momento da Inserção de dados, quando faço isso, qualquer componente que liga a dados que estiver linkado a ClientDataSet e o campo código, ele ficará visível, voce fica sabendo qual o último registro já no momento da Inserção de dados no ClientDataSet.
A outra cajada é que se eu cancelar a inserção de registro, esse autoincremento não será enviada ao banco físico, que repito mais uma vez, só será possível com o acionamento do método Commit do SQLConnection.
GOSTEI 0
Emerson Nascimento
08/07/2009
Discorpio, e no caso de o sistema rodar em rede? Não corre o risco de haver duplicidade de códigos?
GOSTEI 0
Lightshine
08/07/2009
Executa a Trigger no evento Before Insert da tabela e no evento After Insert recupere o código gerado assim:
SELECT GEN_ID(<nome_generator>, 0) FROM RDB$DATABASE
Lightshine.
SELECT GEN_ID(<nome_generator>, 0) FROM RDB$DATABASE
Lightshine.
GOSTEI 0
Lightshine
08/07/2009
Ah! Exqueci de falar...
Você pode usar esta forma de obter o valor do autoincremento caso no seu sistema utilize a dobradinha Generator/Trigger para gerar este codigo.
Lightshine
Você pode usar esta forma de obter o valor do autoincremento caso no seu sistema utilize a dobradinha Generator/Trigger para gerar este codigo.
Lightshine
GOSTEI 0
Discorpio
08/07/2009
Bom dia a todos
Emerson
Neste caso, sim, voce corre o risco de ter registro duplicados em rede, o exemplo que eu dei era para monousuário.
Já em caso de redes, ao se criar uma Trigger no Banco, toda vez que voce inserir um registro voce terá que autoincrementar no banco, só que não devemos esquecer, que quando voce faz inserções com o método Insert ou Append, voce o está fazendo no momento, no TClientDataSet, ou seja, no cache de HD, e não no banco físico. Outro detalhe também é que ao fazer a inserção no TClientDataSet, ele não vai deixar fazer a inserção nele (cache de HD) sem que haja um valor para o código, valor este que não pode ser duplicado, isto porque o TClientDataSet, ao ter os seus registros carregados pelo TDataSetProvider, este também o carregou o MetaData da tabela cujo campo Codigo está configurado como ´Not Null´.
Mas como resolver esta caso então :?:
Adotaremos então a dica do nosso amigo Lightshine, só que com uma diferença, ao invés de se criar a Trigger no banco de dados, crie somente o Generator, e o código que ele postou, voce vai colocar dentro do propriedade SQL do TSQLQuery lá na dica que mencionei, assim:
Agora outro detalhe que não devemos de mencionar, é que com o Generator, corremos o risco de se o usuário cancelar a inserção, de fazemos um autoincremento que não será usado, e o valor autoincrementado ficar orfão no banco físico.
Neste caso, ao invés de usar o evento OnNewRecord, usaremos então o evento OnBeforeInsert do TClientDataSet, assim:
Com o código acima haverá apenas uma diferença, voce autoincrementa diretamente no Banco e não mais na Aplicação e continua fornecendo o valor ao campo código do TCLientDataSet, e ao mesmo tempo recuperando o seu valor autoincrementado.
Mas o porque de não criar a Trigger :?:
Simples, ela só vai ser disparada quando o método Commit do SQLConnection for acionado, e neste caso, o campo código já terá que estar com o seu valor autoincrementado.
Discorpio, e no caso de o sistema rodar em rede? Não corre o risco de haver duplicidade de códigos?
Emerson
Neste caso, sim, voce corre o risco de ter registro duplicados em rede, o exemplo que eu dei era para monousuário.
Já em caso de redes, ao se criar uma Trigger no Banco, toda vez que voce inserir um registro voce terá que autoincrementar no banco, só que não devemos esquecer, que quando voce faz inserções com o método Insert ou Append, voce o está fazendo no momento, no TClientDataSet, ou seja, no cache de HD, e não no banco físico. Outro detalhe também é que ao fazer a inserção no TClientDataSet, ele não vai deixar fazer a inserção nele (cache de HD) sem que haja um valor para o código, valor este que não pode ser duplicado, isto porque o TClientDataSet, ao ter os seus registros carregados pelo TDataSetProvider, este também o carregou o MetaData da tabela cujo campo Codigo está configurado como ´Not Null´.
Mas como resolver esta caso então :?:
Adotaremos então a dica do nosso amigo Lightshine, só que com uma diferença, ao invés de se criar a Trigger no banco de dados, crie somente o Generator, e o código que ele postou, voce vai colocar dentro do propriedade SQL do TSQLQuery lá na dica que mencionei, assim:
Select Gen_ID(<Nome_Generator>,1) as Ultimo From RDB$Database
Agora outro detalhe que não devemos de mencionar, é que com o Generator, corremos o risco de se o usuário cancelar a inserção, de fazemos um autoincremento que não será usado, e o valor autoincrementado ficar orfão no banco físico.
Neste caso, ao invés de usar o evento OnNewRecord, usaremos então o evento OnBeforeInsert do TClientDataSet, assim:
procedure TDM.ClientDataSet1BeforeInsert(DataSet: TDataSet); begin SQLQuery1.Open; ClientDataSet1Codigo.asInteger := SQLQuery1Utimo.asInteger; SQLQuery1.Close; end;
Com o código acima haverá apenas uma diferença, voce autoincrementa diretamente no Banco e não mais na Aplicação e continua fornecendo o valor ao campo código do TCLientDataSet, e ao mesmo tempo recuperando o seu valor autoincrementado.
Mas o porque de não criar a Trigger :?:
Simples, ela só vai ser disparada quando o método Commit do SQLConnection for acionado, e neste caso, o campo código já terá que estar com o seu valor autoincrementado.
GOSTEI 0
Emerson Nascimento
08/07/2009
Bom dia a todos
[quote:f24d4d06b4=´emerson.en´]Discorpio, e no caso de o sistema rodar em rede? Não corre o risco de haver duplicidade de códigos?
Adotaremos então a dica do nosso amigo Lightshine, só que com uma diferença, ao invés de se criar a Trigger no banco de dados, crie somente o Generator, e o código que ele postou, voce vai colocar dentro do propriedade SQL do TSQLQuery lá na dica que mencionei, assim:
Select Gen_ID(<Nome_Generator>,1) as Ultimo From RDB$Database
Neste caso, ao invés de usar o evento OnNewRecord, usaremos então o evento OnBeforeInsert do TClientDataSet, assim:
procedure TDM.ClientDataSet1BeforeInsert(DataSet: TDataSet); begin SQLQuery1.Open; ClientDataSet1Codigo.asInteger := SQLQuery1Utimo.asInteger; SQLQuery1.Close; end;
Com o código acima haverá apenas uma diferença, voce autoincrementa diretamente no Banco e não mais na Aplicação e continua fornecendo o valor ao campo código do TCLientDataSet, e ao mesmo tempo recuperando o seu valor autoincrementado.
Mas o porque de não criar a Trigger :?:
Simples, ela só vai ser disparada quando o método Commit do SQLConnection for acionado, e neste caso, o campo código já terá que estar com o seu valor autoincrementado.[/quote:f24d4d06b4]
perfeito! só questionei porque achei que a sua primeira resposta não traria uma solução definitiva para o colega, podendo, inclusive, gerar um problema diferente do que ele já tinha.
quanto a afirmativa
Agora outro detalhe que não(???) devemos de mencionar, é que com o Generator, corremos o risco de se o usuário cancelar a inserção, de fazemos um autoincremento que não será usado, e o valor autoincrementado ficar orfão no banco físico.
isso nunca foi problema, visto que, na teoria, um campo autoincremento é um campo ´interno´, e também porque esse controle pode ser feito através do DatasetProvider, utilizando o evento BeforeUpdateRecord em conjunto com a opção PropagateChanges, evitando, assim, o código ´órfão´.GOSTEI 0
Lightshine
08/07/2009
Discorpio,
Nosso amigo Lightshine??
Prefiro nossA amigA Lightshine rsrs Sou mulher !!!!
kkkkkkkkkkkkkkkkkkkkkkkkk
T+
Lightshine
Nosso amigo Lightshine??
Prefiro nossA amigA Lightshine rsrs Sou mulher !!!!
kkkkkkkkkkkkkkkkkkkkkkkkk
T+
Lightshine
GOSTEI 0
Discorpio
08/07/2009
Boa tarde a todos
Me desculpe Lightshine, mas não dá pra diferenciar o sexo só pelo codinome ´Brilho da Luz´
De qualquer forma te peço perdão.
Emerson. É por essa razão que eu particularmente não gosto de usar campos autoincrementos quando utilizo o DBExpress.
Em se tratando das tabela Cliente, por exemplo, se ele for pessoa jurídica, eu utilizo como chave primária o campo CNPJ e for pessoa física, eu utilizo o campo RG com chave primária.
Se a tabela for Produtos, utilizo o campo Modelo, ou número de série do produto, e se for Controle de Estoque, faço um gerador de código de controle de estoque, onde anexo o ano, tipo 0930/2009 em uma função que criei para os meus sistemas que só incrementa o número e anexa o ano da data do sistema na string.
Discorpio,
Nosso amigo Lightshine??
Prefiro nossA amigA Lightshine rsrs Sou mulher !!!!
kkkkkkkkkkkkkkkkkkkkkkkkk
T+
Lightshine
Me desculpe Lightshine, mas não dá pra diferenciar o sexo só pelo codinome ´Brilho da Luz´
De qualquer forma te peço perdão.
Emerson. É por essa razão que eu particularmente não gosto de usar campos autoincrementos quando utilizo o DBExpress.
Em se tratando das tabela Cliente, por exemplo, se ele for pessoa jurídica, eu utilizo como chave primária o campo CNPJ e for pessoa física, eu utilizo o campo RG com chave primária.
Se a tabela for Produtos, utilizo o campo Modelo, ou número de série do produto, e se for Controle de Estoque, faço um gerador de código de controle de estoque, onde anexo o ano, tipo 0930/2009 em uma função que criei para os meus sistemas que só incrementa o número e anexa o ano da data do sistema na string.
GOSTEI 0
Lightshine
08/07/2009
Boa tarde a todos
[quote:19b965ce77=´Lightshine´]Discorpio,
Nosso amigo Lightshine??
Prefiro nossA amigA Lightshine rsrs Sou mulher !!!!
kkkkkkkkkkkkkkkkkkkkkkkkk
T+
Lightshine
Me desculpe Lightshine, mas não dá pra diferenciar o sexo só pelo codinome ´Brilho da Luz´
De qualquer forma te peço perdão.
[/quote:19b965ce77]
Discorpio,
Fica tranquilo, esse nick é mesmo bem unisex, já acostumei ^^
Não precisa pedir perdão, eu brinquei só para descontrair um pouco hehe
T+
Lightshine
GOSTEI 0