Select de um BD Insert em Outro
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 }
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
Curtidas 0
Respostas
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 }
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
03/08/2019
Quais campos deseja que fica variavel?
Pelo que entendi, você deseja passar uma variavel
como argumento na query. Seria isso?
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
03/08/2019
Quais campos deseja que fica variavel?
Pelo que entendi, você deseja passar uma variavel
como argumento na query. Seria isso?
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
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 }
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
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
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
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
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:
outra coisa: não se faz if conteudo = True. se é um conteúdo boleando, basta fazer if conteudo
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