psycopg2: insert multiple rows with one query

后端 未结 15 2312
谎友^
谎友^ 2020-11-22 09:11

I need to insert multiple rows with one query (number of rows is not constant), so I need to execute query like this one:

INSERT INTO t (a, b) VALUES (1, 2),         


        
相关标签:
15条回答
  • 2020-11-22 09:58

    execute_batch has been added to psycopg2 since this question was posted.

    It is slower than execute_values but simpler to use.

    0 讨论(0)
  • 2020-11-22 10:00

    A snippet from Psycopg2's tutorial page at Postgresql.org (see bottom):

    A last item I would like to show you is how to insert multiple rows using a dictionary. If you had the following:

    namedict = ({"first_name":"Joshua", "last_name":"Drake"},
                {"first_name":"Steven", "last_name":"Foo"},
                {"first_name":"David", "last_name":"Bar"})
    

    You could easily insert all three rows within the dictionary by using:

    cur = conn.cursor()
    cur.executemany("""INSERT INTO bar(first_name,last_name) VALUES (%(first_name)s, %(last_name)s)""", namedict)
    

    It doesn't save much code, but it definitively looks better.

    0 讨论(0)
  • 2020-11-22 10:02

    Update with psycopg2 2.7:

    The classic executemany() is about 60 times slower than @ant32 's implementation (called "folded") as explained in this thread: https://www.postgresql.org/message-id/20170130215151.GA7081%40deb76.aryehleib.com

    This implementation was added to psycopg2 in version 2.7 and is called execute_values():

    from psycopg2.extras import execute_values
    execute_values(cur,
        "INSERT INTO test (id, v1, v2) VALUES %s",
        [(1, 2, 3), (4, 5, 6), (7, 8, 9)])
    

    Previous Answer:

    To insert multiple rows, using the multirow VALUES syntax with execute() is about 10x faster than using psycopg2 executemany(). Indeed, executemany() just runs many individual INSERT statements.

    @ant32 's code works perfectly in Python 2. But in Python 3, cursor.mogrify() returns bytes, cursor.execute() takes either bytes or strings, and ','.join() expects str instance.

    So in Python 3 you may need to modify @ant32 's code, by adding .decode('utf-8'):

    args_str = ','.join(cur.mogrify("(%s,%s,%s,%s,%s,%s,%s,%s,%s)", x).decode('utf-8') for x in tup)
    cur.execute("INSERT INTO table VALUES " + args_str)
    

    Or by using bytes (with b'' or b"") only:

    args_bytes = b','.join(cur.mogrify("(%s,%s,%s,%s,%s,%s,%s,%s,%s)", x) for x in tup)
    cur.execute(b"INSERT INTO table VALUES " + args_bytes) 
    
    0 讨论(0)
提交回复
热议问题