Trabalhando com 3 tabelas
Preciso fazer um processamento envolvendo 3 tabelas, conforme abaixo, e, não sei como fazer.
1) As tebelas são assim:
Tabela1
cod_cli integer not null,
nome varchar(50),
valor numeric(10,2)
Tabela2
cod_cli integer not null,
evento integer not null,
qtde integer
Tabela3
cod_cli integer not null,
evento integer not null,
total numeric(10,2)
Para cada cod_cli da tabela1 existem diversos cod_cli com eventos diferentes na tabela2, coforme abaixo:
Tabela1
cod_cli Nome Valor
001 Fulano de Tal 100,00
002 Beltrano de Tal 50,00
Tabela2
Cod_cli Evento qtde
001 01 5
001 02 10
002 01 10
002 05 5
2) Preciso gravar na tabela3 o resultado de valor (tabela1) * qtde (tabela2).
3) Estou usando DBExpress com ClientDataSet e estou tentando fazer o código assim:
// Tabela1
(...)
DM.Tabela1.first;
while not dm.tabela1.Eof do
begin
mCod_cli := dm.cdsTabela1COD_CLI.AsInteger;
nQtde := dm.cdsTabela1QTDE.AsInteger;
nValor := dm.cdsTabela1VALOR.AsInteger;
// Tabela2 - DUVIDAS...
Como faço para acessar os registros da Tabela2 com cod_cli = mcod_cli?
Posso fazer um SELECT * Tabela2 WHERE cod_cli = mcod_cli?
Tenho no DataModule 1 SQLQuery, 1 DataSetProvider e 1 ClientDataSet.
Com SQLQuery fica bom ou ficaria melhor com SQLTable ou SQLDataSet?
Como ficaria o código aqui?
?
?
?
?
Solucionada a duvida acima, acho que o código continuaria assim...
DM.Tabela2.first;
while not DM.cdsTabela2.Eof do
begin
mEvento := dm.cdsTabela2EVENTO.AsInteger;
nQtde := dm.cdsTabela2QTDE.AsInteger;
nTotal := nQtde * nValor
// Tabela3 - DUVIDAS
Como faço para gravar aqui?
Posso fazer INSERT INTO TABELA2 (COD_CLI, EVENTO, TOTAL) VALUES (mcod_cli, mevento, nTotal );
De novo tenho, tenho no DataModule 1 SQLQuery, 1 DataSetProvider e 1 ClientDataSet.
Com SQLQuery fica bom ou ficaria melhor com SQLTable ou SQLDataSet?
Como ficaria o código aqui?
?
?
?
ou..
dm.cdsTabela3.Append;
(...)
dm.cdsTabela3.Post;
dm.cdsTabela2.Next;
end;
dm.cdsTabela1.Next;
end;
1) As tebelas são assim:
Tabela1
cod_cli integer not null,
nome varchar(50),
valor numeric(10,2)
Tabela2
cod_cli integer not null,
evento integer not null,
qtde integer
Tabela3
cod_cli integer not null,
evento integer not null,
total numeric(10,2)
Para cada cod_cli da tabela1 existem diversos cod_cli com eventos diferentes na tabela2, coforme abaixo:
Tabela1
cod_cli Nome Valor
001 Fulano de Tal 100,00
002 Beltrano de Tal 50,00
Tabela2
Cod_cli Evento qtde
001 01 5
001 02 10
002 01 10
002 05 5
2) Preciso gravar na tabela3 o resultado de valor (tabela1) * qtde (tabela2).
3) Estou usando DBExpress com ClientDataSet e estou tentando fazer o código assim:
// Tabela1
(...)
DM.Tabela1.first;
while not dm.tabela1.Eof do
begin
mCod_cli := dm.cdsTabela1COD_CLI.AsInteger;
nQtde := dm.cdsTabela1QTDE.AsInteger;
nValor := dm.cdsTabela1VALOR.AsInteger;
// Tabela2 - DUVIDAS...
Como faço para acessar os registros da Tabela2 com cod_cli = mcod_cli?
Posso fazer um SELECT * Tabela2 WHERE cod_cli = mcod_cli?
Tenho no DataModule 1 SQLQuery, 1 DataSetProvider e 1 ClientDataSet.
Com SQLQuery fica bom ou ficaria melhor com SQLTable ou SQLDataSet?
Como ficaria o código aqui?
?
?
?
?
Solucionada a duvida acima, acho que o código continuaria assim...
DM.Tabela2.first;
while not DM.cdsTabela2.Eof do
begin
mEvento := dm.cdsTabela2EVENTO.AsInteger;
nQtde := dm.cdsTabela2QTDE.AsInteger;
nTotal := nQtde * nValor
// Tabela3 - DUVIDAS
Como faço para gravar aqui?
Posso fazer INSERT INTO TABELA2 (COD_CLI, EVENTO, TOTAL) VALUES (mcod_cli, mevento, nTotal );
De novo tenho, tenho no DataModule 1 SQLQuery, 1 DataSetProvider e 1 ClientDataSet.
Com SQLQuery fica bom ou ficaria melhor com SQLTable ou SQLDataSet?
Como ficaria o código aqui?
?
?
?
ou..
dm.cdsTabela3.Append;
(...)
dm.cdsTabela3.Post;
dm.cdsTabela2.Next;
end;
dm.cdsTabela1.Next;
end;
Francisco Rodrigues
Curtidas 0
Respostas
Wesley Yamazack
17/08/2010
Olá amigo,
Estou analisando seu problema, peço que aguarde um pouco.
Obrigado
Um abraço
Wesley Y
Estou analisando seu problema, peço que aguarde um pouco.
Obrigado
Um abraço
Wesley Y
GOSTEI 0
Francisco Rodrigues
17/08/2010
Oi, amigo Wesley,
Meu problema tem solução ou, você não entendeu? Na realidade, preciso:
1) ler uma tabela de funcionarios (tabela 1) e verificar o valor do salario do empregado;
2) verificar na tabela 2 se o empregado fez horas extras;
3) calcular o valor e gravar na tabela 3.
A lógica é assim
Abre Tabela1
Vai para o inicio da tabela1
Enquando o fim do arquivo não for encontrado
guarda codigo do empregado
guarda valor do salario
Abre tabela 2
Verifica se existe o empregado na tabela2
Se existir
Enquanto o codigo do empregado na tabela2 for igual ao codigo do empregado na tabela 1
Calcula e guarda valor calculado
Abre tabela 3
Grava codigo e valor calculado
Volta para tabela 2
Avança 1 registro
fim tabela 2 encontrado
volta para tabela 1
avanca 1 registro
fim tabela 1 encontrado
fim processamento
Estou fazendo assim, mas, a tabela2 fica sempre vazia e, não sei se desta forma fica bom, já que pretendo utilizar o modelo em diversas partes do programa...
procedure TfrmRH3110.btnCalculoFPClick(Sender: TObject);
var
mChapa : Integer;
nSal_Atual,
nHoras_Contratuais,
nSal_Hora,
nSal_Dia,
nSal_Mes : Currency;
mEvento : Integer;
nValor : Currency;
begin
with dmProcessamento do
begin
cdsFuncionario.DisableControls;
cdsFuncionario.First;
while not cdsFuncionario.Eof do
begin
mChapa := cdsFuncionarioCHAPA.AsInteger;
nSal_Atual := cdsFuncionarioSAL_ATUAL.AsCurrency;
nHoras_Contratuais := cdsFuncionarioHORAS_CONTRATUAIS.AsCurrency;
nSal_hora := nSal_Atual/nHoras_Contratuais;
nSal_dia := nSal_Atual/30;
cdsEve.FetchParams;
cdsEve.Params.ParamByName('CHAPA').Value := mChapa;
cdsEve.Open;
if not cdsEve.IsEmpty then {Erro: Aqui fica sempre vazio}
begin
cdsEve.First;
while not cdsEve.Eof do
begin
mEvento := cdsEve.FieldByName('EVENTO').AsInteger;
if cdsEve.FieldByName('VALOR').AsCurrency <> 0 then
nValor := cdsEve.FieldByName('VALOR').AsCurrency
else
nValor := cdsEve.FieldByName('VALOR').AsCurrency * nSal_Hora;
cdsEvn.Append;
cdsEvn.FieldByName('CHAPA').AsInteger := mChapa;
cdsEvn.FieldByName('EVENTO').AsInteger := mEvento;
cdsEvn.FieldByName('VALOR').AsCurrency := nValor;
cdsEvn.Post;
if cdsEvn.ApplyUpdates(0) <> 0 then
cdsEvn.CancelUpdates;
cdsEve.Next;
end;
end;
cdsFuncionario.Next;
end;
cdsFuncionario.EnableControls;
end;
end;
Meu problema tem solução ou, você não entendeu? Na realidade, preciso:
1) ler uma tabela de funcionarios (tabela 1) e verificar o valor do salario do empregado;
2) verificar na tabela 2 se o empregado fez horas extras;
3) calcular o valor e gravar na tabela 3.
A lógica é assim
Abre Tabela1
Vai para o inicio da tabela1
Enquando o fim do arquivo não for encontrado
guarda codigo do empregado
guarda valor do salario
Abre tabela 2
Verifica se existe o empregado na tabela2
Se existir
Enquanto o codigo do empregado na tabela2 for igual ao codigo do empregado na tabela 1
Calcula e guarda valor calculado
Abre tabela 3
Grava codigo e valor calculado
Volta para tabela 2
Avança 1 registro
fim tabela 2 encontrado
volta para tabela 1
avanca 1 registro
fim tabela 1 encontrado
fim processamento
Estou fazendo assim, mas, a tabela2 fica sempre vazia e, não sei se desta forma fica bom, já que pretendo utilizar o modelo em diversas partes do programa...
procedure TfrmRH3110.btnCalculoFPClick(Sender: TObject);
var
mChapa : Integer;
nSal_Atual,
nHoras_Contratuais,
nSal_Hora,
nSal_Dia,
nSal_Mes : Currency;
mEvento : Integer;
nValor : Currency;
begin
with dmProcessamento do
begin
cdsFuncionario.DisableControls;
cdsFuncionario.First;
while not cdsFuncionario.Eof do
begin
mChapa := cdsFuncionarioCHAPA.AsInteger;
nSal_Atual := cdsFuncionarioSAL_ATUAL.AsCurrency;
nHoras_Contratuais := cdsFuncionarioHORAS_CONTRATUAIS.AsCurrency;
nSal_hora := nSal_Atual/nHoras_Contratuais;
nSal_dia := nSal_Atual/30;
cdsEve.FetchParams;
cdsEve.Params.ParamByName('CHAPA').Value := mChapa;
cdsEve.Open;
if not cdsEve.IsEmpty then {Erro: Aqui fica sempre vazio}
begin
cdsEve.First;
while not cdsEve.Eof do
begin
mEvento := cdsEve.FieldByName('EVENTO').AsInteger;
if cdsEve.FieldByName('VALOR').AsCurrency <> 0 then
nValor := cdsEve.FieldByName('VALOR').AsCurrency
else
nValor := cdsEve.FieldByName('VALOR').AsCurrency * nSal_Hora;
cdsEvn.Append;
cdsEvn.FieldByName('CHAPA').AsInteger := mChapa;
cdsEvn.FieldByName('EVENTO').AsInteger := mEvento;
cdsEvn.FieldByName('VALOR').AsCurrency := nValor;
cdsEvn.Post;
if cdsEvn.ApplyUpdates(0) <> 0 then
cdsEvn.CancelUpdates;
cdsEve.Next;
end;
end;
cdsFuncionario.Next;
end;
cdsFuncionario.EnableControls;
end;
end;
GOSTEI 0
Wesley Yamazack
17/08/2010
Olá amigo,
Seguinte você havia me dito que eram 3 tabelas
cdsFuncionario
cdsEve
Onde esta a outra tabela ?
Segundo ponto :
cdsEve.Close; //Adicione o Close para ver se resolve
cdsEve.FetchParams;
cdsEve.Params.ParamByName('CHAPA').AsInteger := mChapa;
cdsEve.Open;
ShowMessage('Valor cdsEve : ' + IntToStr(cdsEve.Params.ParamByName('CHAPA').AsInteger) +#13 +
'Valor mChapa : ' + IntToStr(mChapa)); {Adicione este ShowMessage para poder ver os valores que estão sendo armazenados}
if not cdsEve.IsEmpty then {Erro: Aqui fica sempre vazio}
A única explicação é que o Parametro Chapa, na hora de filtrar não existe o valor mCHapa, para ele estar sempre IsEmpty.
Um abraço,
Wesley Y
Seguinte você havia me dito que eram 3 tabelas
cdsFuncionario
cdsEve
Onde esta a outra tabela ?
Segundo ponto :
cdsEve.Close; //Adicione o Close para ver se resolve
cdsEve.FetchParams;
cdsEve.Params.ParamByName('CHAPA').AsInteger := mChapa;
cdsEve.Open;
ShowMessage('Valor cdsEve : ' + IntToStr(cdsEve.Params.ParamByName('CHAPA').AsInteger) +#13 +
'Valor mChapa : ' + IntToStr(mChapa)); {Adicione este ShowMessage para poder ver os valores que estão sendo armazenados}
if not cdsEve.IsEmpty then {Erro: Aqui fica sempre vazio}
A única explicação é que o Parametro Chapa, na hora de filtrar não existe o valor mCHapa, para ele estar sempre IsEmpty.
Um abraço,
Wesley Y
GOSTEI 0
Francisco Rodrigues
17/08/2010
Olá, amigo.
Adicionando o cdsEve.Close, como você sugeriu, resolveu.
Quanto a 3ª tabela, é cdsEvn, onde gravo o resultado do processamento. Então,
cdsFuncionario - Tabela 1
cdsEve - Tabela 2
cdsEvn - Tabela 3
Fiz esta rotina enquanto aguardava a sua resposta. Não sei se como estou fazendo está correto ou, se de outra forma ficaria melhor. De certa forma estou fazendo como fazia no bom e velho clipper. Desculpe-me, pelas minhas dúvidas de iniciante, mas, as suas dicas são muito importantes para ver se estou fazendo certo, já que vou aplicar isso em outros programas.
Um abraço,
Francisco Rodrigues
Adicionando o cdsEve.Close, como você sugeriu, resolveu.
Quanto a 3ª tabela, é cdsEvn, onde gravo o resultado do processamento. Então,
cdsFuncionario - Tabela 1
cdsEve - Tabela 2
cdsEvn - Tabela 3
Fiz esta rotina enquanto aguardava a sua resposta. Não sei se como estou fazendo está correto ou, se de outra forma ficaria melhor. De certa forma estou fazendo como fazia no bom e velho clipper. Desculpe-me, pelas minhas dúvidas de iniciante, mas, as suas dicas são muito importantes para ver se estou fazendo certo, já que vou aplicar isso em outros programas.
Um abraço,
Francisco Rodrigues
GOSTEI 0
Wesley Yamazack
17/08/2010
Francisco,
O que é mais gratificante neste ramo, ou em qualquer outra, é ajudar pessoas, sejam iniciantes, intermediários, ou avançados, afinal ninguém sabe tudo. Não me peça desculpas por suas dúvidas iniciantes, estamos aqui para lhe ajudar em qualquer situação.
Qualquer dúvida estamos aqui.
Dica : Veja também se consegue assistir algumas vídeo aulas de Delphi, veja os padrões e as formas com que o pessoal trabalha nas vídeos, isso é muito importante para conhecimento. Particularmente, quando estava iniciando, comecei com umas vídeos do Rodrigo Carreiro, muito boas por sinal.
Um abraço
Wesley Y
O que é mais gratificante neste ramo, ou em qualquer outra, é ajudar pessoas, sejam iniciantes, intermediários, ou avançados, afinal ninguém sabe tudo. Não me peça desculpas por suas dúvidas iniciantes, estamos aqui para lhe ajudar em qualquer situação.
Qualquer dúvida estamos aqui.
Dica : Veja também se consegue assistir algumas vídeo aulas de Delphi, veja os padrões e as formas com que o pessoal trabalha nas vídeos, isso é muito importante para conhecimento. Particularmente, quando estava iniciando, comecei com umas vídeos do Rodrigo Carreiro, muito boas por sinal.
Um abraço
Wesley Y
GOSTEI 0