Qual é a melhor maneira de copiar um subconjunto de linhas de uma tabela de um banco para outro no Postgres?

votos
7

Eu tenho um DB produção com, digamos, dez milhões de linhas. Eu gostaria de extrair os 10.000 ou mais linhas de última hora fora de produção e copiá-los para a minha caixa local. Como faço isso?

Vamos dizer que a consulta é:

SELECT * FROM mytable WHERE date > '2009-01-05 12:00:00';

Como faço para fazer a saída, exportá-lo para algum tipo de arquivo de despejo, e depois importar esse arquivo de despejo em minha cópia desenvolvimento local do banco de dados - o mais rápido e fácil possível?

Publicado 06/01/2009 em 00:06
fonte usuário
Em outras línguas...                            


4 respostas

votos
2

De dentro psql, basta usar copycom a consulta que você nos deu, exportar este como um CSV (ou qualquer outro formato), banco de dados switch com \ce importá-lo.

Olhe para \h copyno psql.

Respondeu 06/01/2009 em 00:27
fonte usuário

votos
0

Com a restrição de que adicionou (não sendo superusuário), eu não encontrar uma solução puro-SQL. Mas fazê-lo na sua língua favorita é bastante simples. Você abrir uma conexão com o "velho" banco de dados, um outro para o novo banco de dados, você seleciona em um e INSERIR IGNORE na outra. Aqui é uma solução testada e de trabalho em Python.

 #!/usr/bin/python

""" 

Copy a *part* of a database to another one. See
<http://stackoverflow.com/questions/414849/whats-the-best-way-to-copy-a-subset-of-a-tables-rows-from-one-database-to-anoth>

With PostgreSQL, the only pure-SQL solution is to use COPY, which is
not available to the ordinary user.

Stephane Bortzmeyer <bortzmeyer@nic.fr>

"""

table_name = "Tests"
# List here the columns you want to copy. Yes, "*" would be simpler
# but also more brittle.
names = ["id", "uuid", "date", "domain", "broken", "spf"]
constraint = "date > '2009-01-01'"

import psycopg2

old_db = psycopg2.connect("dbname=dnswitness-spf")
new_db = psycopg2.connect("dbname=essais")
old_cursor = old_db.cursor()
old_cursor.execute("""SET TRANSACTION READ ONLY""") # Security
new_cursor = new_db.cursor()
old_cursor.execute("""SELECT %s FROM %s WHERE %s """ % \
                       (",".join(names), table_name, constraint))
print "%i rows retrieved" % old_cursor.rowcount
new_cursor.execute("""BEGIN""")
placeholders = []
namesandvalues = {}
for name in names:
    placeholders.append("%%(%s)s" % name)
for row in old_cursor.fetchall():
    i = 0
    for name in names:
        namesandvalues[name] = row[i]
        i = i + 1
    command = "INSERT IGNORE  INTO %s (%s) VALUES (%s)" % \
              (table_name, ",".join(names), ",".join(placeholders))
    new_cursor.execute(command, namesandvalues)
new_cursor.execute("""COMMIT""")
old_cursor.close()
new_cursor.close()
old_db.close()
new_db.close()
Respondeu 06/01/2009 em 10:04
fonte usuário

votos
4

servidor de origem:

BEGIN;

CREATE TEMP TABLE mmm_your_table_here AS
    SELECT * FROM your_table_here WHERE your_condition_here;

COPY mmm_your_table_here TO 'u:\\source.copy';

ROLLBACK;

sua caixa de local:

-- your_destination_table_here must be created first on your box

COPY your_destination_table_here FROM 'u:\\source.copy';

Artigo: http://www.postgresql.org/docs/8.1/static/sql-copy.html

Respondeu 06/01/2009 em 10:39
fonte usuário

votos
9

Fonte:

psql -c "COPY (SELECT * FROM mytable WHERE ...) TO STDOUT" > mytable.copy

Destino:

psql -c "COPY mytable FROM STDIN" < mytable.copy

Isso pressupõe mytable tem a mesma ordem de esquema e coluna, tanto a origem eo destino. Se este não é o caso, você pode tentar STDOUT CSV HEADERe STDIN CSV HEADER, em vez de STDOUTe STDIN, mas eu não tentei.

Se você tiver qualquer personalizado dispara em mytable, pode ser necessário desativá-los na importação:

psql -c "ALTER TABLE mytable DISABLE TRIGGER USER; \
         COPY mytable FROM STDIN; \
         ALTER TABLE mytable ENABLE TRIGGER USER" < mytable.copy
Respondeu 08/07/2011 em 18:09
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more