Left Join nao retornou nada

Delphi

01/02/2005

Olá amigos, estou tentando fazer um left join como abaixo:

´Select Vendas.*,Clientes.NomCli FROM Vendas Left Join Clientes ON (Vendas.Codcli=Clientes.CodCli) WHERE (Vendas.CodEmp=:vCodEmp and Vendas.CodEmp=Clientes.CodEmp) ORDER BY Vendas.Data+Vendas.Pedido DESC´;


Após abrir o Client, debugo as variáveis para ver seu conteúdo:

DM.CDS_Vendas.FieldByName(´Pedido´).asstring ---> Traz o valor correto
DM.CDS_Vendas.FieldByName(´CodCli´).asstring ---> Traz o valor correto

Quando debugo a variável NomCli
DM.CDS_Vendas.FieldByName(´NomCli´).asstring ---> Traz o seguinte erro

Delphi exception EDatabaseError at $84BF92D


Aproveitando o tópico, como incluo esse campo no ClientDataSet para acessá-lo no dbGrid? Já que os demais campos da tabela vendas existem fisicamente e já os inclui no DataModule, e esse campo ´Virtual´ NomCli só passou a existir quando da execução dessa Query acima.

O que está errado?

Abraços

Mario


Aldus

Aldus

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

01/02/2005

esteticamente, a instrução ficaria melhor assim:

Select Vendas.*, Clientes.NomCli
FROM Vendas
Left Join Clientes ON (Clientes.CodCli=Vendas.Codcli and Clientes.CodEmp=Vendas.CodEmp)
WHERE Vendas.CodEmp=:vCodEmp
ORDER BY Vendas.Data, Vendas.Pedido DESC

para incluir esse campo no ClientDataset você precisa colocar essa instrução nele e abri-lo em tempo de projeto. Depois você executa os procedimentos normais para inclusão do campo persistente e fecha o ClientDataset.

mas fiquei com um dúvida: porque você tem o campo CodEmp na tabela de clientes?


GOSTEI 0
Aldus

Aldus

01/02/2005

Olá Emerson, que uso o campo codemp porque estou desenvolvendo para poder trabalhar com multiplas empresas dentro do mesmo banco.

Quanto a sua resposta. Eu estou utilizando apenas um clientdataset para cada tabela, nesses casos que tenho que buscar o conteúdo de outras, seria interessante ter um clientdataset apenas para consulta?

Atenciosamente

Mario


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

você pode ter um cds só para consulta ou pode deixar de trabalhar com campos persistentes, criando as colunas de cada grid ´na mão´.


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

quanto ao multi-empresas, é multi-empresas ou multi-filiais?

porque creio que o correto seria ter um banco de dados para cada empresa, e dentro desse banco apontar as filiais. pois supõe-se que todas as filiais tenham o mesmo foco, tanto em clientes quanto em produtos. o que não é necessariamente verdadeiro em se tratando de empresas diferentes.
mesmo porque isso garantiria o bom gerenciamento dos dados, tanto em performance quanto em segurança.

imagine que você tem dados de três empresas distintas num mesmo banco de dados. se por acaso esse banco de dados sofrer algum dano, as três empresas serão prejudicadas (mesmo que momentaneamente), o que não ocorreria se esses dados estivessem distribuídos em três bancos diferentes: apenas uma empresa seria prejudicada.

então, a estrutura deveria ser mais ou menos assim:

bancoXX (onde XX é o código da empresa)
  clientes (não me preocupo com a filial)
    id_cliente
    cnpjcpf
    endereco
    
   
  produtos (não me preocupo com a filial)
    id_produto
    codigo
    nome
    descricao
    

  saldos (me preocupo com a filial)
    id_produto
    id_local
    id_filial
    saldoatual
    
  pedidos (me preocupo com a filial)
    id_pedido
    id_filial
    numero
    data
    

  pedidositens (não me preocupo com a filial, pois está embutida no pedido)
    id_item
    id_pedido
    id_produto
    valorunitario
    quantidade

e assim por diante



GOSTEI 0
Aldus

Aldus

01/02/2005

Emerson, expressei-me errado, o controle é multi-filiais, mas quanto a isso não tenho problemas.

Eu tenho um form de consulta padrão e já crio os campos manualmente, como abaixo, só que como citei acima, era para o campo ´NomCli´ estar disponível quando debugo após a query, não era?

            Lista.DataSource := DM.DS_Vendas ;
            Lista.Columns.Add;
            Lista.Columns[0].FieldName := ´PEDIDO´;
            Lista.Columns[0].Title.Caption:= ´Pedido´;
            Lista.Columns.Add;
            Lista.Columns[1].FieldName := ´DATA´;
            Lista.Columns[1].Title.Caption:= ´Data da Venda´;
            Lista.Columns.Add;
            Lista.Columns[2].FieldName := ´CODCLI´;
            Lista.Columns[2].Title.Caption:= ´Cliente´;
            Lista.Columns.Add;
            Lista.Columns[3].FieldName := ´NOMCLI´;
            Lista.Columns[3].Title.Caption:= ´Nome do Cliente´;
            Lista.Columns.Add;
            Lista.Columns[4].FieldName := ´CODPLA´;
            Lista.Columns[4].Title.Caption:= ´Pagamento´;
            Lista.Columns.Add;
            Lista.Columns[5].FieldName := ´TOTALBRU´;
            Lista.Columns[5].Title.Caption:= ´Total Bruto´;
            Lista.Columns.Add;
            Lista.Columns[6].FieldName := ´TOTALLIQ´;
            Lista.Columns[6].Title.Caption:= ´Total Líquido´;


Até


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

ele só estaria disponível [b:249497d60a]depois de aberta a query[/b:249497d60a] e se [b:249497d60a]não houver campos persistentes[/b:249497d60a].


GOSTEI 0
Aldus

Aldus

01/02/2005

Emerson, por favor examine esse código, que uso para filtrar todos os pedidos e depois apresentá-los no grid

DM.CDS_Vendas.Close ; DM.SQL_Vendas.CommandText := ´Select Vendas.*,Clientes.NomCli as NomCli FROM Vendas Left Join Clientes ON (Vendas.Codcli=Clientes.CodCli) WHERE (Vendas.CodEmp=:vCodEmp and Vendas.CodEmp=Clientes.CodEmp) ORDER BY Vendas.Data+Vendas.Pedido DESC´; DM.SQL_Vendas.ParamByName(´vCodEmp´).AsInteger := fMenu.CodEmpSelec ; DM.CDS_Vendas.Open ;


Após o Open, debugo todos os campos para testar ´dm.cds_vendas.fieldbyname(nomedocampo).asstring´, todos retornam o seu conteúdo, exceto o danado ´NomCli´ que retorna aquele erro ´Delphi exception EDatabaseError at $84BF92D´

O que está errado, a sintaxe da instrução está correta?

Mario


GOSTEI 0
Paulo_amorim

Paulo_amorim

01/02/2005

Olá

Após abrir, debugue e tente verificar:
Só pra começar, o número de campos que o Cds está retornando. Se for diferente do esperado (o total de campos da tabela vendas + NomCli) pode ser isso

Depois, verifique o nome dos campos (Fields[i].FieldName) , principalmente os últimos. Certifique-se de que o seu campo está lá

Provavelmente o erro está em alguma coisa nesses passos... senão ele traria normalmente...

Até+


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

aparentemente não há nada errado, mas estou me perguntando porque não dá erro ao abrir a query, pois você somou o Vendas.Data+Vendas.Pedido, e eu supondo que são campos de tipos diferentes.

como eu disse antes, apenas por estética, eu faria assim:

with DM.CDS_Vendas do
begin
  Close;
  CommandText := ´Select Vendas.*, Clientes.NomCli FROM Vendas ´+
                 ´Left Join Clientes ON (Clientes.CodCli=Vendas.Codcli and Clientes.CodEmp=Vendas.CodEmp) ´+
                 ´WHERE Vendas.CodEmp=:vCodEmp ´+
                 ´ORDER BY Vendas.Data, Vendas.Pedido DESC ´;
  ParamByName(´vCodEmp´).AsInteger := fMenu.CodEmpSelec;
  Open;
end


outra coisa: na tabela Vendas não há um campo [i:940ffb318d]NomCli[/i:940ffb318d], né? Se houver, talvez o sistema esteja se perdendo por não saber qual campo utilizar...


GOSTEI 0
Aldus

Aldus

01/02/2005

Progresso Emerson. No meu datamodule, estavam incluidos todos campos da tabela vendas, é claro menos o NomCli pois o mesmo não existe. Retirei todos os campos do cds, aí apareceu o nome dos clientes. Só que para formatar os valores por exemplo que aparecerão no grid preciso incluí-los no cds para alterar o displayformat, daí incluo somente estes campos numéricos, daí no resultado da query, só me retorna aqueles campos que estão incluídos.

Daí o dilema, se incluo todos no cds, não aparece o NomCli no grid ou se não incluo nenhum, aparece tudo mas não posso formatar os valores no grid, pois como você viu acima, eu incluo os campos em runtime e não há propriedade para formatá-los.

E agora brother, sabes o que posso fazer?


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

foi o que eu te disse acima você ´pode deixar de trabalhar com campos persistentes´....

você pode, sim, criar as máscaras de formatação em tempo de execução.
por exemplo:

depois de abrir a query:
with DM.CDS_Vendas do
begin
  TDateTimeField(FieldByName(´DATA´)).DisplayFormat := ´dd/mm/yyyy´;
  TFloatField(FieldByName(´TOTALBRU´)).DisplayFormat := ´,#0.00´;
  TFloatField(FieldByName(´TOTALLIQ´)).DisplayFormat := ´,0.00´;
end;



GOSTEI 0
Aldus

Aldus

01/02/2005

Salve Salve Emerson! Amigo, acho que é essa a solução, apenas quando declaro o display me dá a seguinte mensagem de erro ´[Error] uConsulta.pas(322): Undeclared identifier: ´TFloatField´´. Está faltando declarar algo em uses né?

Aguardo ancioso seu retorno.

Mario


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

basta declarar a unit DB na cláusula uses.


GOSTEI 0
Aldus

Aldus

01/02/2005

Estou tipo trancado pelos pés cara. Quase lá, mas ainda deu o mesmo erro, declarei no uses e ...
unit uConsulta; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uConsultaPai, StdCtrls, ExtCtrls, Grids, DBGrids, Buttons, ComCtrls, DB;



GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

publique o código exatamente como você fez no Delphi.


GOSTEI 0
Aldus

Aldus

01/02/2005

No uses:
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uConsultaPai, StdCtrls, ExtCtrls, Grids, DBGrids, Buttons, ComCtrls, DB;


Instrução:
fConsulta.Caption := ´Lista de Pedidos´; DM.CDS_Vendas.Close ; DM.SQL_Vendas.CommandText := ´Select Vendas.*,Clientes.NomCli as NomCli FROM Vendas Left Join Clientes ON (Vendas.Codcli=Clientes.CodCli) WHERE (Vendas.CodEmp=:vCodEmp and Vendas.CodEmp=Clientes.CodEmp) ORDER BY Vendas.Data+Vendas.Pedido DESC´; DM.SQL_Vendas.ParamByName(´vCodEmp´).AsInteger := fMenu.CodEmpSelec ; DM.CDS_Vendas.Open ; DM.CDS_Vendas.TFloatField(FieldByName(´TOTALBRU´)).DisplayFormat := ´,#0.00´; DM.CDS_Vendas.TFloatField(FieldByName(´TOTALLIQ´)).DisplayFormat := ´,0.00´;


Até


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

01/02/2005

está errado!

o correto é:

TFloatField(DM.CDS_Vendas.FieldByName(´TOTALBRU´)).DisplayFormat := ´,#0.00´;
TFloatField(DM.CDS_Vendas.FieldByName(´TOTALLIQ´)).DisplayFormat := ´,0.00´;

TFloatField é uma classe distinta, e não um método do ClientDataset.


GOSTEI 0
Aldus

Aldus

01/02/2005

Poxa Emerson, funcionou tudo uma bleza.

Obrigado pelo tempo e paciência em ter me ajudado.

Com certeza, o que aprendi com você vou repassar a outro amigo delphiano que tiver dificuldade.

Obrigado mesmo cara.

Mario


GOSTEI 0
POSTAR