Select de um BD Insert em Outro

03/08/2019

0

Boa noite, fiz um bot que executa scripts sql em um horário pré agendado. Estou fazendo um select em um BD postgreesql e preciso pegar os dados retornados na query e inserir em um BD firebird. O resultado do select é sempre dinâmico e a tabela que recebe os dados tem os mesmos campos e os mesmos tipos que o select de origem.

PostgreSQL 9.6.9
FireBird 3.0
Delphi 10.3

Consegui fazer de forma estática, código abaixo. Porém precisava fazer de forma que os campos possam variar.

with IBGuarani do begin { Query Origem }
Active:=False;
SQL.Clear;
SQL.Add(''select pro_codigo,pro_descricao,pro_referencia from produtos'');
SQL.Free;
Open;
Active:=True;
end;
with IBCatalogo do begin { Query Destino }
Active:=False;
SQL.Clear;
SQL.Add(''insert into produtos (pro_codigo, pro_descricao, pro_referencia)'');
SQL.Add(''values (:pro_codigo, :pro_descricao, :pro_referencia)'');
Prepared:=True;
end;
IBGuarani.First; { Query Origem no primeiro registro }
while not IBGuarani.EOF do begin { Query Origem }
with IBCatalogo do begin { Query Destino / Query Origem }
ParamByName(''pro_codigo'').Value:=IBGuarani.FieldByName(''pro_codigo'').Value;
ParamByName(''pro_descricao'').Value:=IBGuarani.FieldByName(''pro_descricao'').Value;
ParamByName(''pro_referencia'').Value:=IBGuarani.FieldByName(''pro_referencia'').Value;
ExecSQL;
end; { With }
IBGuarani.Next; { Query Origem }
end; { While }
Paulo

Paulo

Responder

Posts

04/08/2019

Gérson

Boa noite, fiz um bot que executa scripts sql em um horário pré agendado. Estou fazendo um select em um BD postgreesql e preciso pegar os dados retornados na query e inserir em um BD firebird. O resultado do select é sempre dinâmico e a tabela que recebe os dados tem os mesmos campos e os mesmos tipos que o select de origem.

PostgreSQL 9.6.9
FireBird 3.0
Delphi 10.3

Consegui fazer de forma estática, código abaixo. Porém precisava fazer de forma que os campos possam variar.

with IBGuarani do begin { Query Origem }
Active:=False;
SQL.Clear;
SQL.Add(''select pro_codigo,pro_descricao,pro_referencia from produtos'');
SQL.Free;
Open;
Active:=True;
end;
with IBCatalogo do begin { Query Destino }
Active:=False;
SQL.Clear;
SQL.Add(''insert into produtos (pro_codigo, pro_descricao, pro_referencia)'');
SQL.Add(''values (:pro_codigo, :pro_descricao, :pro_referencia)'');
Prepared:=True;
end;
IBGuarani.First; { Query Origem no primeiro registro }
while not IBGuarani.EOF do begin { Query Origem }
with IBCatalogo do begin { Query Destino / Query Origem }
ParamByName(''pro_codigo'').Value:=IBGuarani.FieldByName(''pro_codigo'').Value;
ParamByName(''pro_descricao'').Value:=IBGuarani.FieldByName(''pro_descricao'').Value;
ParamByName(''pro_referencia'').Value:=IBGuarani.FieldByName(''pro_referencia'').Value;
ExecSQL;
end; { With }
IBGuarani.Next; { Query Origem }
end; { While }


Quais campos deseja que fica variavel?
Pelo que entendi, você deseja passar uma variavel
como argumento na query. Seria isso?
Responder

04/08/2019

Paulo

Quais campos deseja que fica variavel?
Pelo que entendi, você deseja passar uma variavel
como argumento na query. Seria isso?


Bom dia amigo na verdade não seria essa a intenção. O programa é um bot que na hora agendada vai executar um script .sql que está dentro de uma pasta. O problema é que em cada script executado os select são totalmente diferentes, podendo ser na tabela de vendas, contas a pagar e receber, estoque e assim por diante. Neste exemplo que eu postei eu consegui fazendo isso de forma estática mas eu queria fazer isso de uma forma dinâmica pra evitar atualizações do programa, onde que em caso de alterações só precisasse atualizar o .sql e o problema fosse resolvido.

Simplificando: Preciso fazer o Select no postgree pegar o resultado montar um insert e rodar no firebird.
Responder

04/08/2019

Gérson

Quais campos deseja que fica variavel?
Pelo que entendi, você deseja passar uma variavel
como argumento na query. Seria isso?


Bom dia amigo na verdade não seria essa a intenção. O programa é um bot que na hora agendada vai executar um script .sql que está dentro de uma pasta. O problema é que em cada script executado os select são totalmente diferentes, podendo ser na tabela de vendas, contas a pagar e receber, estoque e assim por diante. Neste exemplo que eu postei eu consegui fazendo isso de forma estática mas eu queria fazer isso de uma forma dinâmica pra evitar atualizações do programa, onde que em caso de alterações só precisasse atualizar o .sql e o problema fosse resolvido.

Simplificando: Preciso fazer o Select no postgree pegar o resultado montar um insert e rodar no firebird.


Bacana.

E se você fizer um script e cada bot.
E um bot (controle) que executa os outros.
Daria certo?

Pelo que entendi você precisa fazer
BOT1:
Insert into Firebird.Tabela_Venda
Values Select * from Postgresql.Tabela_venda

BOT2:
Insert into Firebird.Tabela_Produto
Values Select * from Postgresql.Tabela_produto

BOT3:
Insert into Firebird.Tabela_Cliente
Values Select * from Postgresql.Tabela_Cliente

BOT_Controle:
Executa bot1;
Executa bot2;
Executa bot3;

Isso ajuda?
Responder

04/08/2019

Claudio Andrade

Boa noite, fiz um bot que executa scripts sql em um horário pré agendado. Estou fazendo um select em um BD postgreesql e preciso pegar os dados retornados na query e inserir em um BD firebird. O resultado do select é sempre dinâmico e a tabela que recebe os dados tem os mesmos campos e os mesmos tipos que o select de origem.

PostgreSQL 9.6.9
FireBird 3.0
Delphi 10.3

Consegui fazer de forma estática, código abaixo. Porém precisava fazer de forma que os campos possam variar.

with IBGuarani do begin { Query Origem }
Active:=False;
SQL.Clear;
SQL.Add(''select pro_codigo,pro_descricao,pro_referencia from produtos'');
SQL.Free;
Open;
Active:=True;
end;
with IBCatalogo do begin { Query Destino }
Active:=False;
SQL.Clear;
SQL.Add(''insert into produtos (pro_codigo, pro_descricao, pro_referencia)'');
SQL.Add(''values (:pro_codigo, :pro_descricao, :pro_referencia)'');
Prepared:=True;
end;
IBGuarani.First; { Query Origem no primeiro registro }
while not IBGuarani.EOF do begin { Query Origem }
with IBCatalogo do begin { Query Destino / Query Origem }
ParamByName(''pro_codigo'').Value:=IBGuarani.FieldByName(''pro_codigo'').Value;
ParamByName(''pro_descricao'').Value:=IBGuarani.FieldByName(''pro_descricao'').Value;
ParamByName(''pro_referencia'').Value:=IBGuarani.FieldByName(''pro_referencia'').Value;
ExecSQL;
end; { With }
IBGuarani.Next; { Query Origem }
end; { While }


Se estiver usando o FireDac dê uma olhada no funcionamento do FDLocalSQL, ele resolve o seu problema.
Responder

04/08/2019

Paulo


Bacana.

E se você fizer um script e cada bot.
E um bot (controle) que executa os outros.
Daria certo?

Pelo que entendi você precisa fazer
BOT1:
Insert into Firebird.Tabela_Venda
Values Select * from Postgresql.Tabela_venda

BOT2:
Insert into Firebird.Tabela_Produto
Values Select * from Postgresql.Tabela_produto

BOT3:
Insert into Firebird.Tabela_Cliente
Values Select * from Postgresql.Tabela_Cliente

BOT_Controle:
Executa bot1;
Executa bot2;
Executa bot3;

Isso ajuda?


É exatamente isso porém via código eu não consegui encontrar um meio que funcionasse.

Se estiver usando o FireDac dê uma olhada no funcionamento do FDLocalSQL, ele resolve o seu problema.


Estou usando o FireDac sim, dei uma pesquisada sobre mas não consegui realizar o insert dessa forma. Sabe algum lugar tem um exemplo fazendo o select e depois o insert? Todos os exemplos que eu encontrei só fazem select.
Responder

05/08/2019

Emerson Nascimento

Bom dia amigo na verdade não seria essa a intenção. O programa é um bot que na hora agendada vai executar um script .sql que está dentro de uma pasta. O problema é que em cada script executado os select são totalmente diferentes, podendo ser na tabela de vendas, contas a pagar e receber, estoque e assim por diante. Neste exemplo que eu postei eu consegui fazendo isso de forma estática mas eu queria fazer isso de uma forma dinâmica pra evitar atualizações do programa, onde que em caso de alterações só precisasse atualizar o .sql e o problema fosse resolvido.

você não poderia ter na pasta as duas instruções? a de select e a de insert? algo assim:
bot1sel.sql
bot1 ins.sql
bot2sel.sql
bot2 ins.sql
ou seja: sempre haveria 2 scripts para cada tabela manipulada.
daí o teu programa seria mais ou menos assim:
with IBGuarani do { Query Origem }
begin
	Close
	SQL.Clear;
	SQL.Add( select_obtida_do_arquivo_aaansel.sql );
	Open;
end;

with IBCatalogo do { Query Destino }
begin
	Close;
	SQL.Clear;
	SQL.Add( insert_obtida_do_arquivo_aaanins.sql );
	Prepare;
end;

IBGuarani.First; { Query Origem no primeiro registro }
while not IBGuarani.EOF do { Query Origem }
begin
	with IBCatalogo do { Query Destino / Query Origem }
	begin
		for i := 0 to IBGuarani.Fields.Count-1 do
			ParamByName(IBGuarani.Fields[i].FieldName).Value := IBGuarani.Fields[i].Value;
		ExecSQL;
	end; { With }
	IBGuarani.Next; { Query Origem }
end; { While }


ou ainda ter somente o script de select e obter dali a tabela pra gerar o insert. nesse caso a select precisaria ter uma regra específica, para que fosse possível identificar a tabela destino. se você puder publicar um script vai possibilitar a você receber ajuda mais precisa.
Responder

05/08/2019

Paulo

for i := 0 to IBGuarani.Fields.Count-1 do
			ParamByName(IBGuarani.Fields[i].FieldName).Value := IBGuarani.Fields[i].Value;


Eu não tinha pensando nisso, simplesmente simples e resolveu o meu problema. Fica aqui o meu muito obrigado.

Vou deixar aqui embaixo como ficou.

{ Pega o nome dos Scripts a ser Executado  }
  if DM.FDConnectionFB.Connected = True then begin
    with qryTarefa do begin
      Close;
      SQL.LoadFromFile(ScriptDirSelect + 'TarefaAgendada.sql');
      Open;
    end;
  end;
  { Executa o Script Encontado }
  if DM.FDConnectionPG.Connected = True then begin
    { Vai executar todos os scripts que encontrou }
    qryTarefa.First;
    while not qryTarefa.EOF do begin
      with qryPG do begin
        Close;
        SQL.LoadFromFile(ScriptDirSelect + qryTarefa.FieldByName('SCRIPT_NAME').Text);
        Open;
        Active:=True;
      end;
      { Carrega o Script de Insert }
      with qryInsert do begin
        Close;
        SQL.Clear;
        SQL.LoadFromFile(ScriptDirInsert + qryTarefa.FieldByName('SCRIPT_NAME_INSERT').Text);
        Prepare;
      end;
      qryPG.First; { Query Origem no primeiro registro }
      while not qryPG.EOF do begin { Query Origem }
        with qryInsert do begin { Query Destino / Query Origem }
          for i:= 0 to qryPG.Fields.Count -1 do begin
            qryInsert.ParamByName(qryPG.Fields[i].FieldName).Value:=qryPG.Fields[i].Value;
            ExecSQL;
          end;
        end; { With }
      qryPG.Next; { Query Origem }
      end; { While }
    end;


Obrigado a todos, forte abraço!
Responder

06/08/2019

Emerson Nascimento

não está certo.... o ExecSQL do insert não deveria estar dentro do for. precisa ficar fora, como no exemplo.
o correto deveria ser isso:
{ Pega o nome dos Scripts a ser Executado  }
  if DM.FDConnectionFB.Connected then
  begin
    with qryTarefa do
    begin
      Close;
      SQL.LoadFromFile(ScriptDirSelect + 'TarefaAgendada.sql');
      Open;
    end;
  end;
  { Executa o Script Encontado }
  if DM.FDConnectionPG.Connected then
  begin
    { Vai executar todos os scripts que encontrou }
    qryTarefa.First;
    while not qryTarefa.EOF do
    begin
      with qryPG do
      begin
        Close;
        SQL.LoadFromFile(ScriptDirSelect + qryTarefa.FieldByName('SCRIPT_NAME').Text);
        Open;
//        Active:=True; // Open e Active=True são o mesmo comando.
      end;
      { Carrega o Script de Insert }
      with qryInsert do
      begin
        Close;
        SQL.Clear;
        SQL.LoadFromFile(ScriptDirInsert + qryTarefa.FieldByName('SCRIPT_NAME_INSERT').Text);
        Prepare;
      end;
      qryPG.First; { Query Origem no primeiro registro }
      while not qryPG.EOF do { Query Origem }
      begin
        with qryInsert do { Query Destino / Query Origem }
        begin
          // o FOR não precisa de begin porque só tem uma linha
          for i := 0 to qryPG.Fields.Count -1 do
            ParamByName(qryPG.Fields[i].FieldName).Value:=qryPG.Fields[i].Value;
          ExecSQL; // este comando está fora do FOR
        end; { With }
        qryPG.Next; { Query Origem }
      end; { While }
    end;

outra coisa: não se faz if conteudo = True. se é um conteúdo boleando, basta fazer if conteudo
Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar