Select de um BD Insert em Outro

PostgreSQL

Delphi

Firebird

03/08/2019

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

Curtidas 0

Respostas

Gérson

Gérson

03/08/2019

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?
GOSTEI 0
Paulo

Paulo

03/08/2019

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.
GOSTEI 0
Gérson

Gérson

03/08/2019

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?
GOSTEI 0
Claudio Andrade

Claudio Andrade

03/08/2019

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.
GOSTEI 0
Paulo

Paulo

03/08/2019


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.
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

03/08/2019

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.
GOSTEI 0
Paulo

Paulo

03/08/2019

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!
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

03/08/2019

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
GOSTEI 0
POSTAR