Transportando dados entre bases PostgreSQL

Uma necessidade comum quando se administra um ambiente com versões diferentes de esquemas de bases de dados é o transporte de parte destes dados de uma base mais atualizada (como uma base de homologação por exemplo) para uma base com dados desatualizados (como uma base de testes ou de desenvolvimento).

Em um post anterior demonstrei como podemos melhorar a visualização do psql distinguindo servidores de produção dos de teste e desenvolvimento através de cores do prompt. Neste demonstro como transportar os dados de uma base para outra de maneira mais produtiva, desde que você tenha em mãos um pouco de conhecimento em expressões regulares e alguns ingredientes especiais.

Nota! Tá meio “enferrujado” em regex? Dê uma olhada no site do Aurélio ou no do Perl ou neste sobre sed e regex “:D

Suponha que temos em nossa base de dados TESTE uma massa de dados necessário para testar determinada funcionalidade de um sistema. Agora imagine que um determinado desenvolvedor necessite de parte desta massa de dados para depurar uma tela ainda na base de DESENVOLVIMENTO. Ocorre que nem todos os dados desta base podem ser sobrescritos, e que o desenvolvedor não precisa de nenhum dado a mais além do necessário.

Nesta caso, podemos fazer uso de mecanismos simples de exportação de dados e filtragem destes dados, utilizando o pg_dump e o egrep por exemplo. Para o exemplo estou pressupondo a seguinte estrutura de tabelas:

TB_PESSOA

CPF numeric(12)
NOME character varying(50)
...

TB_FUNCIONARIO

CPF_PESSOA (FK)
CARGO numeric(3)
...

Você pode exportar os dados desta base através da ferramenta pg_dump, cujas opções que valem destacar são:

  • -a ou –data-only : indica ao pg_dump que somente os dados devem ser extraídos;
  • -D ou –column-inserts: indica ao pg_dump que o dump gerado ao invés de utilizar instruções COPY, irá utilizar INSERT com os nomes de colunas, muito importante para o exemplo que vamos trabalhar;
  • -t ou –table : indica ao pg_dump qual(is) tabela(s) deve(m) ser exporta(s) Suponha que a saída do pg_dump da base de TESTE seja mais ou menos assim:
$ pg_dump -U postgres -aDt tb_pessoa teste
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (10, 109878776122, 'LEONARDO SILVA');
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (11, 827318818273, 'MARCIO SOUZA');
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (12, 123118987273, 'MARILENE SANTOS');
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (13, 919281283818, 'POLIANA M. T.');
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (14, 071717128833, 'JACK NILSON');
INSERT INTO tb_pessoa (id, cpf, nome) VALUES (15, 012930131239, 'MARIA G. T.');
$ pg_dump -U postgres -aDt tb_funcionario teste
INSERT INTO tb_funcionario (id, cargo) VALUES (10, 2);
INSERT INTO tb_funcionario (id, cargo) VALUES (11, 2);
INSERT INTO tb_funcionario (id, cargo) VALUES (12, 1);
INSERT INTO tb_funcionario (id, cargo) VALUES (13, 4);
INSERT INTO tb_funcionario (id, cargo) VALUES (14, 4);
INSERT INTO tb_funcionario (id, cargo) VALUES (15, 1);

Você também pode simplificar em um único comando:

$ pg_dump -U postgres -aD -t tb_funcionario -t tb_pessoa teste

A saída destes comandos nada mais são do que arquivos textos que contém um padrão de exibição de cada linha. Desta forma podemos filtrar determinadas linhas utilizando o egrep para isto. Em nosso exemplo, imagine que o desenvolvedor solicite a cópia dos dados de funcionário e pessoa dos códigos 10,12 e 15, basta você fazer:

$ pg_dump -aDt tb_pessoa teste | egrep "VALUES \(1(0|2|5)," | psql -d desenvolvimento $ pg_dump -aDt tb_funcionario teste | egrep "VALUES \(1(0|2|5)," | psql -d desenvolvimento

Ou ainda o desenvolvedor pode precisar de uma faixa de valores, por exemplo do 12 ao 14.

$ pg_dump -aDt tb_pessoa teste | egrep "VALUES \(1[2-4]," | psql -d desenvolvimento $ pg_dump -aDt tb_funcionario teste | egrep "VALUES \(1[2-4]," | psql -d desenvolvimento

Com essa pequena base os resultados são pequenos, mas quando você possui uma base de tamanho considerável obterá melhores resultados. Teste várias expressões regulares e você irá se familiarizar com as várias saídas possíveis que obterá.

Nota! É sempre importante testar o filtro antes de redirecioná-lo para o psql para que não haja imprevistos…

comments powered by Disqus