Delphi + Mysql + Tabela Vendas x Itens_vendas
Bom dia pessoal já procurei por ai até achei topicos com a mesma duvida mas nenhuma solução que me serve.
Tenho um sistema Delphi XE8 com Mysql 5 usando Componentes DBExpres. O que preciso parece simples mas não é.
Tenho uma tabela de VENDAS e outra ITENS_VENDAS. O campo que liga as duas tabelas é o ID_VENDA. Onde na tabela VENDA ele é Auto_Increment, pois bem.
Como obter o valor ID_VENDA, para lançar na tabela ITENS_VENDA antes de gravar no banco? ( o comando LAST_INSERT_ID() não funciona, ou então não sei usar, sempre retorna o valor 0).
Ahhh mas então vc da um post e depois pega o numero. OK mas e se o usuario desistir da venda? como desfaço o post?
Alguém tem um exemplo de como trabalhar no delphi com essa relação de tabelas?
Tenho um sistema Delphi XE8 com Mysql 5 usando Componentes DBExpres. O que preciso parece simples mas não é.
Tenho uma tabela de VENDAS e outra ITENS_VENDAS. O campo que liga as duas tabelas é o ID_VENDA. Onde na tabela VENDA ele é Auto_Increment, pois bem.
Como obter o valor ID_VENDA, para lançar na tabela ITENS_VENDA antes de gravar no banco? ( o comando LAST_INSERT_ID() não funciona, ou então não sei usar, sempre retorna o valor 0).
Ahhh mas então vc da um post e depois pega o numero. OK mas e se o usuario desistir da venda? como desfaço o post?
Alguém tem um exemplo de como trabalhar no delphi com essa relação de tabelas?
Casa
Curtidas 0
Melhor post
Jones Granatyr
16/09/2016
Olá,
Sobre essa parte: "OK mas e se o usuario desistir da venda? como desfaço o post?"
Poderia também verificar se existe algum item, caso não faz um delete na venda
Jones
Sobre essa parte: "OK mas e se o usuario desistir da venda? como desfaço o post?"
Poderia também verificar se existe algum item, caso não faz um delete na venda
Jones
GOSTEI 1
Mais Respostas
Huidemar Costa
16/09/2016
Boa Tarde!
A forma que eu faria é salvar o "cabeçalho" da nota(Id_Venda, Numero, data, cliente/fornecedor), tendo feito isso terei o ID_VENDA, feito isso eu incluiria os itens da nota.
A tabela poderia ter um campo para dizer se a venda foi finalizada, caso não tenha sido finalizada, ou seja, o usuário desistiu da venda, ele exclui a Nota.
A forma que eu faria é salvar o "cabeçalho" da nota(Id_Venda, Numero, data, cliente/fornecedor), tendo feito isso terei o ID_VENDA, feito isso eu incluiria os itens da nota.
A tabela poderia ter um campo para dizer se a venda foi finalizada, caso não tenha sido finalizada, ou seja, o usuário desistiu da venda, ele exclui a Nota.
GOSTEI 0
Kellson
16/09/2016
usa o comando Max(codigo)+1 acho que no mysql deve ser mesma logica que no sql
select Max(id) from cliente
ou
select @@identity as 'ULTIMOID' +1
select Max(id) from cliente
ou
select @@identity as 'ULTIMOID' +1
GOSTEI 0
Kellson
16/09/2016
vc deveria usar o CDS Virtual, assim vc pode manusear ate estornar antes de efetivar no banco de dados.
GOSTEI 0
Kellson
16/09/2016
olha como eu faria, como id da venda gera uma unica vez com autoincrement, Identity, entao vc precisa fazer apenas um insert onde gera o id da venda e grava todos os itens com id da venda capturado certo.
faz um Virtual Clientdataset para armazenar os itens temporario, faça uma fct ou SP no proprio delphi para quando form lançando item ja somando para vc
botao finalizar
with query_venda do
begin
close;
sql.clear;
sql.text:='insert into venda(colunas) values( valores);
execsql;
sql.clear;
sql.text:='select Max(IVENDA) as ULTIMOID from venda;
VARIAVEL INTEGER OU STRING:=query.fieldbyname(ULTIMOID).value;
sql.clear;
sql.text:='select * from venda' // para nao dar exception not result
open;
end;
ate agora vc tem o id da venda
entao agora vem
while not(clientdataset.eof) do
begin
with query_ITEMVENDA do
begin
sql.add('insert into itemvenda(codigovenda,item,etc) values('+quotedstr(StringCodVenda)+',item,etc);
end;
clientdataset.next;
end
with adoquery_itemvenda do
begin
execsql;
end;
gambiarra pura kkkkkk, unica coisa que passou rapido pela minha cabeça, mas é claro se tiver fazendo na hora surge ideias melhores.
faz um Virtual Clientdataset para armazenar os itens temporario, faça uma fct ou SP no proprio delphi para quando form lançando item ja somando para vc
botao finalizar
with query_venda do
begin
close;
sql.clear;
sql.text:='insert into venda(colunas) values( valores);
execsql;
sql.clear;
sql.text:='select Max(IVENDA) as ULTIMOID from venda;
VARIAVEL INTEGER OU STRING:=query.fieldbyname(ULTIMOID).value;
sql.clear;
sql.text:='select * from venda' // para nao dar exception not result
open;
end;
ate agora vc tem o id da venda
entao agora vem
while not(clientdataset.eof) do
begin
with query_ITEMVENDA do
begin
sql.add('insert into itemvenda(codigovenda,item,etc) values('+quotedstr(StringCodVenda)+',item,etc);
end;
clientdataset.next;
end
with adoquery_itemvenda do
begin
execsql;
end;
gambiarra pura kkkkkk, unica coisa que passou rapido pela minha cabeça, mas é claro se tiver fazendo na hora surge ideias melhores.
GOSTEI 0
Kellson
16/09/2016
olha como eu faria, como id da venda gera uma unica vez com autoincrement, Identity, entao vc precisa fazer apenas um insert onde gera o id da venda e grava todos os itens com id da venda capturado certo.
faz um Virtual Clientdataset para armazenar os itens temporario, faça uma fct ou SP no proprio delphi para quando form lançando item ja somando para vc
botao finalizar
with query_venda do
begin
close;
sql.clear;
sql.text:='insert into venda(colunas) values( valores);
execsql;
sql.clear;
sql.text:='select Max(IVENDA) as ULTIMOID from venda;
open <--------------------------------------------------------------------------------------------------------------- // abrir para trazer o resultado
VARIAVEL INTEGER OU STRING:=query.fieldbyname(ULTIMOID).value;
close;
sql.clear;
end;
ate agora vc tem o id da venda
entao agora vem
while not(clientdataset.eof) do
begin
with query_ITEMVENDA do
begin
sql.add('insert into itemvenda(codigovenda,item,etc) values('+quotedstr(StringCodVenda)+',item,etc);
end;
clientdataset.next;
end
with adoquery_itemvenda do
begin
execsql;
end;
gambiarra pura kkkkkk, unica coisa que passou rapido pela minha cabeça, mas é claro se tiver fazendo na hora surge ideias melhores.
faz um Virtual Clientdataset para armazenar os itens temporario, faça uma fct ou SP no proprio delphi para quando form lançando item ja somando para vc
botao finalizar
with query_venda do
begin
close;
sql.clear;
sql.text:='insert into venda(colunas) values( valores);
execsql;
sql.clear;
sql.text:='select Max(IVENDA) as ULTIMOID from venda;
open <--------------------------------------------------------------------------------------------------------------- // abrir para trazer o resultado
VARIAVEL INTEGER OU STRING:=query.fieldbyname(ULTIMOID).value;
close;
sql.clear;
end;
ate agora vc tem o id da venda
entao agora vem
while not(clientdataset.eof) do
begin
with query_ITEMVENDA do
begin
sql.add('insert into itemvenda(codigovenda,item,etc) values('+quotedstr(StringCodVenda)+',item,etc);
end;
clientdataset.next;
end
with adoquery_itemvenda do
begin
execsql;
end;
gambiarra pura kkkkkk, unica coisa que passou rapido pela minha cabeça, mas é claro se tiver fazendo na hora surge ideias melhores.
GOSTEI 0
Casa
16/09/2016
Mas para uma aplicação em rede onde dois ou mais usuários irão utilizar ao mmsm tempo nao da problema de violar a chave primaria?
GOSTEI 0
Kellson
16/09/2016
nao da problema nao,pois so gera id quando o cliente requisita insert , entao o banco no servidor vai gerar o ID com o generator identity.
puts amigo nao tenho nenhum projeto, perdi meu HD com os projetos , porem ja fiz isso.
puts amigo nao tenho nenhum projeto, perdi meu HD com os projetos , porem ja fiz isso.
GOSTEI 0
Casa
16/09/2016
nao da problema nao,pois so gera id quando o cliente requisita insert , entao o banco no servidor vai gerar o ID com o generator identity.
puts amigo nao tenho nenhum projeto, perdi meu HD com os projetos , porem ja fiz isso.
puts amigo nao tenho nenhum projeto, perdi meu HD com os projetos , porem ja fiz isso.
Então fiz o teste aqui, e usar o comando MAX vai dar problema com a chave sim, ele só gera o id quando posta, se duas pessoas abrir uma venda ao memso tempo vai gerar o mesmo ID.
Consegue um exemplo pra mim?
GOSTEI 0
Raimundo Pereira
16/09/2016
Boa tarde,
Uma alternativa é Criar uma tabela temporária.
TMP_Venda
ID_VENDA,Usado
Então, abriu a tela de vendas a primeira coisa é gerar um id e salvar na TMP_VENDA.
O próximo usuário em rede irá gerar um novo ID.
O número fica resguardado, Após comitt basta realizar um updade USADO=SIM.
Uma alternativa é Criar uma tabela temporária.
TMP_Venda
ID_VENDA,Usado
Então, abriu a tela de vendas a primeira coisa é gerar um id e salvar na TMP_VENDA.
O próximo usuário em rede irá gerar um novo ID.
O número fica resguardado, Após comitt basta realizar um updade USADO=SIM.
GOSTEI 0
Kellson
16/09/2016
como vc fez? pois o sql aceita em seguimento os comandos não simultâneo na tabela, exemplo: executar comando 1 e comando 2
1 - insert +1 =2
2 - insert +1=3
e nao simultaneo 1,2
1 - insert +1 =2
2 - insert +1=3
e nao simultaneo 1,2
GOSTEI 0
Kellson
16/09/2016
faz uma procedure então onde da um set var=Identity para pegar ultimo numero da do gerador assim inserindo nos itens
GOSTEI 0
Kellson
16/09/2016
exemplo seria isso aqui : gerar proximo id com o proprio gerador do banco , pegar o ip da venda para utilizar nos itens, usa o identity para pegar ultimo id, e logo abaixo na mesma procedure usa outro insert para os itens, com id da venda.
create procedure inserir
@nome varchar(max),
@idade integer
as
insert into cliente(nome,idade) values(@nome,@idade)
select @@IDENTITY as 'ULTIMOID'
create procedure inserir
@nome varchar(max),
@idade integer
as
insert into cliente(nome,idade) values(@nome,@idade)
select @@IDENTITY as 'ULTIMOID'
GOSTEI 0
Luiz Freitas
16/09/2016
Olá!
Peluchi,
Como os outros usuários sugeriram, existem outras formas de fazer isso de dentro do Delphi mesmo, utilizando CachedUpdate por exemplo, mas eu não me lembro como faz, então vou sugerir uma solução que já utilizei e funcionou perfeitamente:
> Crie uma tabela para controle dos ID's, você pode controlar os ID's de todas as tabelas nas quais operações parecidas com essa (venda + item) precise ocorrer;
> No formulário de venda, ao iniciar uma nova venda você consulta a tabela de controle de ID's, pega o valor gravado nela, adiciona mais um (e já realiza o update na tabela de controle para que ele fique atualizada) e reserva esse valor;
> Os dados do cabeçalho da Venda, juntamente com o ID gerado, ficam gravados temporariamente em um ClientDataSet (CDS) ou em um FDMemTable (FMT), assim eles não são gravados diretamente no banco, ficam em memória até o processo ser concluído;
> Assim como no caso da Venda, insira os itens, utilizando como ID da Venda o valaor reservado anteriormente, também em um CDS ou em um FMT (para que eles fiquem em memória até o momento da gravação no banco);
> Caso a venda seja confirmada, transfira os dados para as tabelas de Vendas e de Itens no o banco de dados;
> Caso a venda seja interrompida por qualquer motivo simplesmente limpe o CDS ou FMT e estará tudo cancelado.
Em qualquer uma das situações, seja usando CachedUpdates, com um campo auto-incremento na própria tabela, ou usando a solução que sugeri, criando uma tabela para controlar os ID's, o ID que foi reservado para ser utilizado na venda iniciada (que pode se confirmar ou não) é perdido caso a operação não seja confirmada/concluída com sucesso.
Espero que você encontre uma solução que te atenda adequadamente.
Se quiser utilizar minha sugestão e tiver alguma dúvida é só perguntar.
Boa sorte!
Att,
Luiz
Peluchi,
Como os outros usuários sugeriram, existem outras formas de fazer isso de dentro do Delphi mesmo, utilizando CachedUpdate por exemplo, mas eu não me lembro como faz, então vou sugerir uma solução que já utilizei e funcionou perfeitamente:
> Crie uma tabela para controle dos ID's, você pode controlar os ID's de todas as tabelas nas quais operações parecidas com essa (venda + item) precise ocorrer;
> No formulário de venda, ao iniciar uma nova venda você consulta a tabela de controle de ID's, pega o valor gravado nela, adiciona mais um (e já realiza o update na tabela de controle para que ele fique atualizada) e reserva esse valor;
> Os dados do cabeçalho da Venda, juntamente com o ID gerado, ficam gravados temporariamente em um ClientDataSet (CDS) ou em um FDMemTable (FMT), assim eles não são gravados diretamente no banco, ficam em memória até o processo ser concluído;
> Assim como no caso da Venda, insira os itens, utilizando como ID da Venda o valaor reservado anteriormente, também em um CDS ou em um FMT (para que eles fiquem em memória até o momento da gravação no banco);
> Caso a venda seja confirmada, transfira os dados para as tabelas de Vendas e de Itens no o banco de dados;
> Caso a venda seja interrompida por qualquer motivo simplesmente limpe o CDS ou FMT e estará tudo cancelado.
Em qualquer uma das situações, seja usando CachedUpdates, com um campo auto-incremento na própria tabela, ou usando a solução que sugeri, criando uma tabela para controlar os ID's, o ID que foi reservado para ser utilizado na venda iniciada (que pode se confirmar ou não) é perdido caso a operação não seja confirmada/concluída com sucesso.
Espero que você encontre uma solução que te atenda adequadamente.
Se quiser utilizar minha sugestão e tiver alguma dúvida é só perguntar.
Boa sorte!
Att,
Luiz
GOSTEI 0