What's the best way to copy a subset of a table's rows from one database to another in Postgres?

后端 未结 4 1367
我在风中等你
我在风中等你 2021-02-04 17:52

I\'ve got a production DB with, say, ten million rows. I\'d like to extract the 10,000 or so rows from the past hour off of production and copy them to my local box. How do I do

相关标签:
4条回答
  • 2021-02-04 17:59

    From within psql, you just use copy with the query you gave us, exporting this as a CSV (or whatever format), switch database with \c and import it.

    Look into \h copy in psql.

    0 讨论(0)
  • 2021-02-04 18:02

    source server:

    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;
    

    your local box:

    -- your_destination_table_here must be created first on your box
    
    COPY your_destination_table_here FROM 'u:\\source.copy';
    

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

    0 讨论(0)
  • 2021-02-04 18:05

    Source:

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

    Destination:

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

    This assumes mytable has the same schema and column order in both the source and destination. If this isn't the case, you could try STDOUT CSV HEADER and STDIN CSV HEADER instead of STDOUT and STDIN, but I haven't tried it.

    If you have any custom triggers on mytable, you may need to disable them on import:

    psql -c "ALTER TABLE mytable DISABLE TRIGGER USER; \
             COPY mytable FROM STDIN; \
             ALTER TABLE mytable ENABLE TRIGGER USER" < mytable.copy
    
    0 讨论(0)
  • 2021-02-04 18:05

    With the constraint you added (not being superuser), I do not find a pure-SQL solution. But doing it in your favorite language is quite simple. You open a connection to the "old" database, another one to the new database, you SELECT in one and INSERT in the other. Here is a tested-and-working solution in 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 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()
    
    0 讨论(0)
提交回复
热议问题