Ir para conteúdo
Fórum Script Brasil
  • 0

Criar campos no table apartir de query


robinhocne

Pergunta

18 respostass a esta questão

Posts Recomendados

  • 0

Estava escrevendo agora...rsrsrs

Vamos la, eu tenho a tabela criada no banco, mas tem campos nela que eu não quero trazer.

Tenho uma consulta dinamica que traz uns dados, então precisava pegar esses campos dessa query que executou a consulta, criar os fields na tabela, o nome da tabela pela consulta eu já sei, então passo no table (o componente table já tenho no form) e ai quando eu der um open ele irá trazer somente os dados dos campos que eu quero que era da consulta.

 

Link para o comentário
Compartilhar em outros sites

  • 0

Vamos la, eu tenho a tabela criada no banco, mas tem campos nela que eu não quero trazer.

exemplo: vamos supor que voce tem uma tabela com varios campos e precisa apenas de alguns deles:

na select voce pode especificar somente os campos que voce quer trazer

select campo1, campo2, campo5, campo8 from tabela

ou no object inspector do clientdataset voce joga somente os campos que quer que apareçam

select * from tabela

no clientdataset voce deixa somente os campos que quer.

--------------------------------------------

ou voce pode criar uma tabela temporaria com os dados da consulta via query, mas acho que a sugestão acima resolve.

a não ser que voce queira adicionar outros campos na tabela alem dos que já existem.

abraço

 

 

Link para o comentário
Compartilhar em outros sites

  • 0

Não seria isso Jhonas, vou explicar melhor...

Estou criando um sistema de integração, então estou criando o dinamicamente algumas configurações, como são bancos diferentes e tabelas diferentes, faço um de para e nesse de para eu tenho o select das informações que ira trazer o banco a para o banco b, porém a tabela do banco b tem uns campos á mais que não são necessários.

Para fazer todo esse processo estou usando o Firedac ETL com o delphi Berlin, onde quando consulto eu tenho esses dados da imagem, coloquei o grid só para ver os campos, o primeiro grid é os registros que será enviados para outra tabela pelo BatchMove, eu liguei o BatchMove com o BatchMoveDataSetWriter e ele liguei com um table.

As setas do grid b são os campos que tem na tabela b e que não mando, eu não tenho como colocar um table para cada tabela porque são vários e para ficar dinamico.

Se passo assim no table

            table.TableName := NOMEDATABELA;
            table.Open;

ele traz todos os campos

...... ixi agora que percebi um problema, quando faço open ele traz os dados que estão na tabela, com isso pesando....

Jhonas....como faço pelo batchmove jogar os dados, porque o teste que tinha feito eu tinha colocado um table e quando executei o proprio BatchMove se encarregou de inserir e atualizar os dados, fazer a saida do BatchMoveDataSetWriter por uma query tem como ?

esquece sobre pegar os campos da query, porque já via adiantar já que ao abrir a tabela ele lista tudo...

Sem título.png

Link para o comentário
Compartilhar em outros sites

  • 0

Jhonas me dá uma ajuda por favor.....

Estou consultando a tabela com esse sql;

                  instSql := 'SELECT column_name as nm_campo,data_type as ds_tipo ';
                  instSql := instSql + ' FROM information_schema.columns ';
                  instSql := instSql + ' WHERE table_name ='''+qryCamposDEPARA.FieldByName('nm_tabelapara').AsString+'''';
                  instSql := instSql + ' order by column_name';

				 with dtmPSyncBack.qryPesquisar do
                    begin
                       Active := false;
                       Close;
                       sql.Clear;
                       sql.add(instSql);
                       open;
                    end;

                  while not dtmPSyncBack.qryPesquisar.Eof do
                    begin
                        with FDMemTable1 do
                          begin
                             FieldDefs.Add(dtmPSyncBack.qryPesquisar.FieldByName('nm_campo').AsString,
                                            qryCamposDEPARA.FieldByName('nm_tipopara').DataType,
                                            qryCamposDEPARA.FieldByName('nm_tipopara').Size,
                                            false);
                          end;

                        BatchMove.Mappings.Add;
                        with BatchMove.Mappings do
                          begin
                           Items[i].SourceFieldName      := dtmPSyncBack.qryPesquisar.FieldByName('nm_campo').AsString;
                           Items[i].DestinationFieldName := dtmPSyncBack.qryPesquisar.FieldByName('nm_campo').AsString;
                          end;

                        i := i + 1;
                      dtmPSyncBack.qryPesquisar.Next;
                    end;

                 dtmPSyncBack.qryPesquisar.close;

              FDMemTable1.Open;

             BatchMove.Execute();

Então quando executa o batchMove eu tenho esse erro ;

First chance exception at $76D3A9F2. Exception class EFDException with message '[FireDAC][Comp][DM]-608. Undefined source field or expression for destination field [%s]'.

 

Link para o comentário
Compartilhar em outros sites

  • 0

As setas do grid b são os campos que tem na tabela b e que não mando,

no componente Table, voce pode escolher quais os campos da tabela voce quer ( duplo clique com o botão esquerdo no componente e adicione apenas os campos que voce precisa )

fazer a saida do BatchMoveDataSetWriter por uma query tem como ?

nunca fiz, mas acho que é possivel

http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/FireDAC.TFDBatchMove_Sample

OBS: porque voce não cria uma tabela com todos os campos que voce precisa da tabela A e da tabela B, e simplesmente joga os resultados nela ?

 

quanto ao erro:

Exceção de primeira chance em $ 76D3A9F2. Classe de exceção EFDException
com mensagem '[FireDAC] [Comp] [DM] -608. Campo ou expressão de origem
indefinida para o campo de destino [% s] '.

voce colocou um campo que não existe ou não foi definido para a tabela destino

Link para o comentário
Compartilhar em outros sites

  • 0

Então....peguei uma tabela que é iguais de ambos lados....e mesmo assim tenho esse erro, veja....

http://prntscr.com/f71roo

o batchmove mapeie

http://prntscr.com/f71ryl

e os campos coloquei na tabela

http://prntscr.com/f71s7c

 

e mesmo assim dá o erro

Exceção de primeira chance em $ 76D3A9F2. Classe de exceção EFDException
com mensagem '[FireDAC] [Comp] [DM] -608. Campo ou expressão de origem
indefinida para o campo de destino [% s] '.

 

no componente Table, voce pode escolher quais os campos da tabela voce quer ( duplo clique com o botão esquerdo no componente e adicione apenas os campos que voce precisa )

não tenho como fazer, porque não sei a tabela, consultando os campos vou saber o nome da tabela e por isso teria que criar em tempo de execução, mas estou tentando fazer com um memory table, que também cheguei com o mesmo erro acima;

Link para o comentário
Compartilhar em outros sites

  • 0

o erro pode estar no proprio componente BatchMove

já peguei erros assim, e depois de quebrar muito a cabeça, o erro não estava no código

que eu estava montando, mas sim no código do componente.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Provider, DBClient, DB, StdCtrls, DBTables, Grids, DBGrids;

type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    DBGrid2: TDBGrid;
    Table1: TTable;
    Table2: TTable;
    Button1: TButton;
    DataSource1: TDataSource;
    DataSource2: TDataSource;
    Table1NUM: TFloatField;
    Table1CODIGO_FS: TStringField;
    Table1DATA: TDateField;
    Table1AUTOR: TStringField;
    Table1VOLUME: TStringField;
    Table1SINOPSE: TMemoField;
    BatchMove1: TBatchMove;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
    y: Integer;
    nCount: Integer;
    cField: TField;
    cName: array[0..100] of String;
    cType: array[0..100] of TFieldType;
    nSize: array[0..100] of Integer;
    bReqd: array[0..100] of Boolean;
begin

      with Table1 do
      begin
         Active := False;

         DatabaseName := 'C:\';
         TableName := 'Source';
         nCount := FieldCount;
         for y := 0 to nCount - 1 do
         begin
           cField   := Table1.Fields[y];
           cName[y] := cField.FieldName;
           cType[y] := cField.DataType;
           nSize[y] := cField.Size;
           bReqd[y] := cField.Required;
         end;
     end;

     with Table2 do
     begin
        Active := False;
        DatabaseName := 'C:\';
        TableName := 'Destination';
        TableType := ttDefault;
        with FieldDefs do
        begin
          Clear;
          for y := 0 to nCount - 1 do begin
            Add(cName[y], cType[y], nSize[y], bReqd[y]);
          end;
        end;
     CreateTable;
end;

end;

end.

esse código copia a estrutura do Table1 para o Table2 corretamente

depois bastaria popular os campos

 

Link para o comentário
Compartilhar em outros sites

  • 0

Ok, vou ver....

Jhonas....uma opnião por favor, qual seria o melhor metodo para sincronizar dados, na verdade vou consultar dados da base SQLServer e fazer insert/update no PostGre, agora saber quando atualizar ou inserir ai terei que consultar se o registro houve alteração a todo insert ?

Link para o comentário
Compartilhar em outros sites

  • 0

voce vai achar muito material na internet versando sobre o assunto

https://www.google.com.br/?gws_rd=ssl#q=sincronizar+base+de+dados+sql+server

entretanto de forma prática, se os dados da base SQLServer ( Servidor ) esta distante do ( Cliente )  e essa atualização seria via internet ou intranet, voce pode optar por usar um banco de dados local e replicar as alterações no Servidor.

se a conexão não for problema, então voce pode verificar se houve alteração a todo insert ou update direto no banco do Servidor.

se houver restrição na conexão ( falhas )  então, trabalhe com um banco local e faça a atualização do Servidor sempre em segundo plano  ( Threads )

https://www.google.com.br/?gws_rd=ssl#q=threads+delphi+example

dessa maneira voce não trava a aplicação na atualização do banco de dados. neste caso o controle sobre os processos devem ser muito bem estruturados.

abraço

 

Link para o comentário
Compartilhar em outros sites

  • 0

Obrigado Jhonas, o banco está no mesmo local, só em maquinas separadas, então internet e rede não será o problema, já queria utilizar algo pronto, mas a ideia é essa, tenho o banco local, só não queria trazer uns 1000 registros e dar um loop nele para verificar quem atualizou para atualizou ou inserir, mas de qualquer forma vou gravar no registro que ele foi atualizado, assim vou garantir mais a integridade.

 

Então...fiz o seguinte, instalei o Tokyo e testei e dá os mesmos erros, utilizando o mode dmAlwaysInsert tanto o MoveSQLWriter e DataSetWriter funciona, porém quando estou usando o MoveSQLWriter e mudo o mode para dmAppendUpdate ele dá erro de 

[Firedac][Phys]-609.Key fields are not defined.

e quando mudo para o DataSetWriter ele dá erro de:

[Firedac][Comp][DM]-608.Undefined source field or expression for destination field [%s]

Estive pesquisando sobre o dmAppendUpdate e ele:

Para anexar e atualizar dados, o conjunto de dados de destino deve representar uma tabela existente e deve ter um índice definido que permita que os registros sejam correspondidos. Se os campos de índice primário forem usados para correspondência, os registros com campos de índice no dataset de destino que correspondem aos registros de campos de índice no conjunto de dados de origem são substituídos pelos dados de origem. Caso contrário, os dados do conjunto de dados de origem são anexados ao conjunto de dados de destino. Durante as operações de anexação e atualização, o BDE converte os dados em tipos e tamanhos de dados apropriados para o conjunto de dados de destino, se necessário.

Criei os indices nas duas tabelas e mesmo assim está dando erro, creio que eu esteja fazendo alguma coisa errada, estou anexando o teste que estou fazendo com um banco firebird mesmo onde tento jogar dados da tabela bancos para etl_bancos só para teste.

https://www.4shared.com/zip/JpKijal8ca/ETL.html

CREATE TABLE BANCOS (
	CODIGO INTEGER,
	BANCO VARCHAR(20)
) ;
CREATE INDEX BANCOS_CODIGO_IDX ON BANCOS (CODIGO) ;

  
  CREATE TABLE ETL_BANCOS (
	CODIGO INTEGER,
	NOME VARCHAR(20)
) ;
CREATE INDEX ETL_BANCOS_CODIGO_IDX ON ETL_BANCOS (CODIGO) ;

//criei o campo nome do banco diferente de proprosito para ver o mapeamento de campos trabalhando corretamente.

Me ajuda, por favor.

Link para o comentário
Compartilhar em outros sites

  • 0

https://www.4shared.com/zip/JpKijal8ca/ETL.html

My 4shared_1494683550399.zip

OBS: O arquivo zip esta vazio.

[Firedac][Phys]-609.Key fields are not defined.

Os campos chaves não estão definidos

[Firedac][Comp][DM]-608.Undefined source field or expression for destination field [%s]

Campo ou expressão de origem indefinida para o campo de destino

com relação a isso, veja o link

https://translate.google.com.br/translate?hl=pt-BR&sl=en&u=http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Unique_Identifying_Fields_(FireDAC)&prev=search

não tenho o Firedac, então fica dificil ajuda-lo nesse ponto.

o banco está no mesmo local, só em maquinas separadas, então internet e rede não será o problema, já queria utilizar algo pronto, mas a ideia é essa, tenho o banco local, só não queria trazer uns 1000 registros e dar um loop nele para verificar quem atualizou para atualizou ou inserir, mas de qualquer forma vou gravar no registro que ele foi atualizado, assim vou garantir mais a integridade.

se o banco de dados esta no mesmo local, não é necessario trabalhar com outro banco  local.

tenho um sistema funcionando dessa maneira. o banco esta em um servidor com outras maquinas acessando-o. O banco tem algumas tabelas com mais de 200.000 registros e trago apenas de 100 em 100 registros na tela.  ( uma rede de 1Gb )  bem rapido.

a atualização dos dados é feita diretamente no banco via ClientDataSet ( que é uma copia da tabela que estou trabalhando no momento )  se houver algum problema, só perco o ultimo registro.

uma solução bem simples para voce, é criar um campo de controle na tabela

nesse campo voce indica que tipo de atualização será feita.

exemplo: usando um campo numerico

1 - insert

2 - update

depois voce cria uma rotina somente para ler esse campo e executar esse procedimento na tabela destino ...  fica muito rapido.

abraço

Link para o comentário
Compartilhar em outros sites

  • 0

acho que dessa maneira mesmo que você falou no final vai ser melhor, vou criar um campo de data de integração(timestamp), caso não tenha essa data ele não foi enviando, nas tabelas eu já tenho a data de cadastro(timestamp) que é registrado quando o registro é inserido, então quando a data de cadastro for maior que a data de integração ele deve atualizar o registro....isso dá para separar os sql que vai retornar, nesse caso vou ver para gerar os insert's e update's em lotes que vai ser mais rapido....

De qualquer forma, vou tentar pedir ajuda da Embarcadero para descobrir como funciona esses componentes....

Jhonas agradeço a atenção, sei que o tópico tomou rumo diferente do iniciado, mas realmente estava desesperado em como solucionar....

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...