Erro ao inserir em tb com campos identitiy no sql server 2008
Pessoal isso mesmo, na hora de inserir um registro o clientdataset não esta mandando para o banco, no meu entender o campo identity e como um default ou como se existisse um trigger para disparalo, vejam a vídeo e retornem o mais rápido possível
[#VIDEO-179#]
[#VIDEO-179#]
Carlos Faria
Curtidas 0
Respostas
Carlos Faria
18/02/2010
Rodrigo um vez eu abri um chamado onde o banco nao tava querendo inserir lembra que voce ate fez uma transação para tentar forçar o registro a entrar no banco , acho que esse chamado e o mesmo daquele ,porem agora eu ja identifiquei que o problema pelo menos na versao 2008 do sql e o campo identity
GOSTEI 0
Carlos Faria
18/02/2010
Ola Rodrigo eu outra vez,
Bom eu pesquisei aqui e encontrei uma solução que não me parece nada boa, daria uma trabalheira danada e perderia muito em produtividade. Fiz o seguinte teste criei duas tabelas diferentes Tb_teste1 e Tb_Teste2 com os mesmo parâmetros, para cada clientdataset eu adicionei um sqldataset e um datasetprovider ou seja , fiquei em um único datamodule com 2 sqldataset e 2 datasetprovider sendo que setando a propriedade poAllowCommandtext de um datasetprovider eu poderia adicionar quantos clientdataset quisesse. Sendo assim a meu ver se tiver outra maneira e não precisar fazer assim um trio para cada clientdataset (sqldataset, datasetprovider, clientdataset) eu agradeceria. Mas a palavra final ai e sua.
GOSTEI 0
Carlos Faria
18/02/2010
e claro esqueci de falar o mais importante no sqldataset adicionei os fields e ai sim , informei que o campo id nao é requerido , ai deu tudo certo ! mas dessa maneira acho trabalhoso demais
se possivel uma video caprichada , ja faz tempo que tu nao faz uma rs
GOSTEI 0
Rodrigo Mourão
18/02/2010
Certo carlos, vou gravar e te envio,
GOSTEI 0
Carlos Faria
18/02/2010
Ok Rodrigo
Fico esperando mais uma vez , retifico usar um sqlconnetion + sqldataset + datasetprovider com a propriedade poAllowCommandtext para true é um maravilha isso , agente precisa de criar apenas um trio de componentes e vai adicionando clientdataset , porem quando o campo e identity so da certo se agente adicionar o tfields na sqldataset e dizer que o campo autoincremento não é requerido. Bom isso para mim não é bom pois teria que colocar centenas de componentes no projeto , centenas de sqldataset e datasetprovider . se tiver um jeito de driblar isso agradeço muito
GOSTEI 0
Rodrigo Mourão
18/02/2010
Segue a Video:
http://video.devmedia.com.br/discovirtual/162135/Chamado_15827_Final.rar
Att,
http://video.devmedia.com.br/discovirtual/162135/Chamado_15827_Final.rar
Att,
GOSTEI 0
Carlos Faria
18/02/2010
VOU ANALIZAR TUDO AQUI E TE RETORNO O MAIS RAPIDO POSSIVEL
GOSTEI 0
Rodrigo Mourão
18/02/2010
Ok,
Estamos aguardando então.
Abs!!!
Estamos aguardando então.
Abs!!!
GOSTEI 0
Carlos Faria
18/02/2010
Ola grande Rodrigo.
Bom eu fiz alguns ajustes aqui, exatamente como você fez no seu sistema de vendas. Praticamente quase do mesmo jeito.
Agora eu vou inserir na tabela Tb_vendas aquele resumo da venda, qt_items,Subtotal ,Id_Cliente e etc. , nessa tabela o campo será autoimcremento.Na tabela itens vendas ai sim vou inserir todos os itens daquela venda , porem eu preciso capturar o id_venda antes de inserir e não pode ser como você me mostrou no vídeo pois será uma grande quantidade de maquinas assecando o sistema.
A pergunta é
Como eu vou capturar o id_venda usando Delphi ,sqlserver e dbexpress ?
Eu poderia criar uma procudere de insert na Tb_vendas como um campo @retorno pegar o id_venda e trabalhar com ele na Tb_items_Venda , mas ficaria estranho , clientdataset , sqlproc e etc
Da uma luz meste
Não preciso que o usuário veja o numero Id_Venda na tabela , apenas que após inserir na Tb_vendas , eu pegue e id_venda , e jogue no clientdaset que vai inserir na Tb_intens venda
É claro tudo isso ficara dentro de uma transação, se não se houver algum erro posso inserir na tabela Tb_vendas e não ter itens relacionados com aquela venda;
GOSTEI 0
Carlos Faria
18/02/2010
cdsItemVenda.Open ;
cdsItemVenda.First;
while not cdsItemVenda.Active do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ;
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0); tenho 2 clientdaset um de memoria e outro conectado , peguei o exemplo la no teu curso , so nao sei o que estou fazerndo de errado aqui , cdsitems e o clientdataset offline , cdsitemvenda o que finaliza , enato seja se o camarada encher o grid com 15 pedidos tenho que gravar os 15 registros , o que ta errado aqui ????????? outra questao e a situação que te informei no texto anterior , por ser uma quantidade grande de maquinas acessando o sistema , nao pode haver erros e questao de capturar o id eu ja resolvi com um stored procedure id_venda int output select @@identity as @retorno , a proc insere , me traz o numero e inserio nos detalhes , mas to achando isso meio porcao afinal estou trabalhando com clientdataset , me diz vc o que achas ? aquele seu exemplo de como capturar o id_antes do insert no sql server eu nao consegui se vc tiver um exemplo mais claro ai agradeço outra coisa o exemplo que vc me demostrou com a query funciona sim ,testei aqui , mais poder haver error serissiomos se mais de um atendente acessar ao mesmo tempo , melhor tentarmos uma solucao meslhoe estive analizando a seguinte situação talves nesse caso a proc seja melhor , pois eu nao vou ter um id_venda na tela somente quando ela realmente for concluida , e posso fazer tudo isso dentro de uma transacao , cadastro a venda e itens da venda , assim se mais de um usuario acessar o sistema ao mesmo tempo nao tem erro , afinal o campo e do tipo identiy e so vou ter ele depois de inserido os registros ? vc que é o mestre ai , da uma ideia que eu faço aqui , Quanto a questao do Loop cara se puder ser hoje ainda urgente , passei a noite toda enrolado tentando fazer esse loop funcionar aqui rs
GOSTEI 0
Rodrigo Mourão
18/02/2010
Carlos Esta dando mole kk
O metodo e while not cdsItemVenda.EOF do e não while not cdsItemVenda.Active do
Veja como ficaria:
cdsItemVenda.Open ;
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ;
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
Abs!!
O metodo e while not cdsItemVenda.EOF do e não while not cdsItemVenda.Active do
Veja como ficaria:
cdsItemVenda.Open ;
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ;
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
Abs!!
GOSTEI 0
Carlos Faria
18/02/2010
na verdade o metodo active eu escrevi pq escrevi rapido e sem revisar o que acontece é o seguinte
cdsItemVenda.Open ; //cdsligado ao banco
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ; //cds de memoria
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
Cdsitemvenda é co clientdaset que vai dar um insert nao tb_item_vendas esse cds e conectado a banco Cdsitems esse e de memoria , offline como vc diz , nao esta funcionando o lação , eu copiei e colei exatamente como vc mandou nao esta varrendo os dados inseridos na grid ???????????????
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ; //cds de memoria
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
Cdsitemvenda é co clientdaset que vai dar um insert nao tb_item_vendas esse cds e conectado a banco Cdsitems esse e de memoria , offline como vc diz , nao esta funcionando o lação , eu copiei e colei exatamente como vc mandou nao esta varrendo os dados inseridos na grid ???????????????
GOSTEI 0
Rodrigo Mourão
18/02/2010
Roda a aplicacao com F9 executa e tentar gravar.
Me manda a mensagem do erro ou se prefirir grave um video me mostrando como tudo esta conectado e como vc fez o codigo que fica mais facil.
Estou no aguardo !!
Attt,
Me manda a mensagem do erro ou se prefirir grave um video me mostrando como tudo esta conectado e como vc fez o codigo que fica mais facil.
Estou no aguardo !!
Attt,
GOSTEI 0
Carlos Faria
18/02/2010
Aqui eu ja achei o erro , o que aconteceu foi que voce fez o mesmo erro que eu ,rs o clientdataset que precisa entrar no loop é o cdsitems (clientdataset) de memoria e nao o clientdataset do banco oberve nas linhas vermelhas que apos alterado tudo deu certo agora ,posso encher a grid que grava tudo,porem ainda ta dando um erro apenas eu coloque isso dentro de um bloco de transaction
procedure TfrmVendas.btnConfirmaClick(Sender: TObject);
var
t: TDBXTransaction;
begin
try
t := DM.SQLConnection.DBXConnection.BeginTransaction(TDBXIsolations.ReadCommitted);
pri_vendas;
pri_item_venda;
DM.SQLConnection.DBXConnection.CommitFreeAndNil(t); except
DM.SQLConnection.DBXConnection.RollbackFreeAndNil(t);
//ShowMessage(Venda nao realizada ');
end;
end; a procedure pri_items_Venda nada mais e que cdsItemVenda.Open;
cdsItems.First;
while not cdsItems.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := xVenda;
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger; cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0); porem ao colocar um brack point ele entra nessa rotina do cliente dataset e fica em loop infinito e nao roda
codigo correto cdsItemVenda.Open;
cdsItems.First;
while not cdsItems.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := xVenda;
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger; cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0);
seu codigo (alias nosso codigo melhor dizendo eu e vc caimos no mesmo erro rs)
cdsItemVenda.Open ; //cdsligado ao banco
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ; //cds de memoria
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
var
t: TDBXTransaction;
begin
try
t := DM.SQLConnection.DBXConnection.BeginTransaction(TDBXIsolations.ReadCommitted);
pri_vendas;
pri_item_venda;
DM.SQLConnection.DBXConnection.CommitFreeAndNil(t); except
DM.SQLConnection.DBXConnection.RollbackFreeAndNil(t);
//ShowMessage(Venda nao realizada ');
end;
end; a procedure pri_items_Venda nada mais e que cdsItemVenda.Open;
cdsItems.First;
while not cdsItems.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := xVenda;
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger; cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0); porem ao colocar um brack point ele entra nessa rotina do cliente dataset e fica em loop infinito e nao roda
codigo correto cdsItemVenda.Open;
cdsItems.First;
while not cdsItems.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := xVenda;
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger; cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat; cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next; cdsItemVenda.Post;
end;
cdsItemVenda.ApplyUpdates(0);
seu codigo (alias nosso codigo melhor dizendo eu e vc caimos no mesmo erro rs)
cdsItemVenda.Open ; //cdsligado ao banco
cdsItemVenda.First;
while not cdsItemVenda.EOF do
begin
cdsItemVenda.Append;
cdsItemVendaid_venda.AsInteger := 29; //colocar a variavel aqui
cdsItemVendaId_Produto.AsInteger := cdsItems.FieldByName('codigo').AsInteger;
cdsItemVendaQt_Items.AsFloat := cdsItems.FieldByName('quantidade').AsFloat;
cdsItemVendaVl_Produto.AsFloat := cdsItems.FieldByName('preco').AsFloat;
cdsItemVendaId_Vendedor.AsInteger := 1;
cdsItems.Next ; //cds de memoria
cdsItemVenda.Post;
end ;
cdsItemVenda.ApplyUpdates(0);
GOSTEI 0
Rodrigo Mourão
18/02/2010
kkkkkkkkkkkkk
Putz que mole ein. kkkk Realmente não reparei. Mas tai ja pegou o jeito da depuração.
Att,
Putz que mole ein. kkkk Realmente não reparei. Mas tai ja pegou o jeito da depuração.
Att,
GOSTEI 0
Carlos Faria
18/02/2010
mas o que vc me diz da transação , é necessaria afinal vou inserir em 2 tabelas diferentes ou faço isso tudo com clientdatset mesmo
GOSTEI 0
Rodrigo Mourão
18/02/2010
Olá Carlos,
Desculpe esqueci de mencionar isso.
Não precisa de transação o clientDataSet ja faz transsação interno por isso que mesmo se você der post ele nao grava no banco tem que ser APplyUpdates.
Funciona assim: Voce da Append 10 vezes no ClientDataSet no final vc dar Applyupdates(0). Neste momento ele abra a transacao e tenta gravar os 10 por isso que a gente passa 0 no parametro para dizer qeu aceitamos 0 erro, ou seja, tem que gravar tudo.
Entao nao precisa criar transacao explicita nao.
Att,
Desculpe esqueci de mencionar isso.
Não precisa de transação o clientDataSet ja faz transsação interno por isso que mesmo se você der post ele nao grava no banco tem que ser APplyUpdates.
Funciona assim: Voce da Append 10 vezes no ClientDataSet no final vc dar Applyupdates(0). Neste momento ele abra a transacao e tenta gravar os 10 por isso que a gente passa 0 no parametro para dizer qeu aceitamos 0 erro, ou seja, tem que gravar tudo.
Entao nao precisa criar transacao explicita nao.
Att,
GOSTEI 0
Carlos Faria
18/02/2010
Para finalizar so falta uma coisa , como te disse a estrutura das tabelas são as seguintes
Tb_vendas
Id_venda (autoincremento
Id_cliente
quantidade
Valor
Data
Tb_items_venda
Id_venda
id_produto
Vl_unidade
Qt_itens
Tb_entregas
Id_venda
Id_cliente
Vl_compra
Nr_entregador
data
Observe que nas 3 tabelas eu vou precisar do id_venda .
Primeiro eu insiro na Tb_vendas pego o id_venda jogo nuna variável e passo para os outros CDs
Existe alguma função interna no clientedataset onde eu possa capturar esse id_venda e jogalo em uma variável ?
Eu fiz um exemplo aqui usando um storedproc , criei uma procedure de insert no SQL
Parametro1
Parametro2
@Idvenda int output
Insert into Tb_vendas (campos1,campos2,etc) values (parâmetros)
Select @idvenda as identity
Funcionou perfeito pois, a proc insere e traz um retorno , esse retorno eu jogo na variaves e passo para os outros clientdataset , mas a duvida e a seguinta , fica meio estranho usar clientdatase e stroredproc na aplicação
como eu vou captruar esse id usando clientdataset ?
GOSTEI 0
Rodrigo Mourão
18/02/2010
Olá CArlos,
Na verdade quando o problema ai e o seguinte, você so terá o ID quando ter o APplyUpdate para dar o ApplyUpdates vc tem que ter o ID por isso eu sugeri o lance da tabela para gerar o ID mas esta solução com StroredProc ficou muito melhor pois concentra a geração do ID no banco.
Att,
Na verdade quando o problema ai e o seguinte, você so terá o ID quando ter o APplyUpdate para dar o ApplyUpdates vc tem que ter o ID por isso eu sugeri o lance da tabela para gerar o ID mas esta solução com StroredProc ficou muito melhor pois concentra a geração do ID no banco.
Att,
GOSTEI 0
Rodrigo Mourão
18/02/2010
Ol´aCarlos,
Podemos encerrar o chamado ??
Att,
Podemos encerrar o chamado ??
Att,
GOSTEI 0
Carlos Faria
18/02/2010
Ultima pergunta antes de fechar o chamado , trabalhar com storedproc , e clientdataset nao ficaria meio estanho , ou ficaria tudo bem ao seu ver ??????
respode e pode fechar o chamado !
GOSTEI 0
Rodrigo Mourão
18/02/2010
Se cada um fizer a sua parte não há problemas.
Por exemplo usar Stored proc para Inserir, Alterar ou Deletar e reinventar a roda. O CDS faz isso automatico. Da mesma forma que usar CDS para Alterar um registro e retorna-lo em seguida nao compensa neste caso a Procedure cai como uma luva.
att,
Por exemplo usar Stored proc para Inserir, Alterar ou Deletar e reinventar a roda. O CDS faz isso automatico. Da mesma forma que usar CDS para Alterar um registro e retorna-lo em seguida nao compensa neste caso a Procedure cai como uma luva.
att,
GOSTEI 0
Carlos Faria
18/02/2010
Fecha ai entao ! ok
GOSTEI 0