使用asyncpg插入多行的最佳方法

时间:2017-05-02 13:27:10

标签: python postgresql python-asyncio asyncpg

我想插入多行并使用asyncpg获取ID,我发现了两种方法: 1:生成像这样的SQL

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy')
RETURNING id;

2:在for循环中使用prepared语句

values =(('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
        ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'))
stmnt = connection.prepare("INSERT INTO films (code, title, did, date_prod, kind) VALUES $1, $2, $3, $4, $5  RETURNING id")
for val in values:
    stmnt.fetchval(*val)

我必须更喜欢100x次700,000行的情况,还是有办法将这些方法结合起来? 我完全是绿色的,所以在我身上扔一些tomattoes

2 个答案:

答案 0 :(得分:6)

如果您需要使用RETURNING子句来获取ID,那么以下是插入多个值的最有效方法:

res = await conn.fetch('''
    INSERT INTO films (code, title, did, date_prod, kind)
    (SELECT
        r.code, r.title, r.did, r.date_prod, r.kind
     FROM
        unnest($1::films[]) as r
    )
    RETURNING id
''', [
    (None, 'B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    (None, 'HG120', 'The Dinner Game', 140, None, 'Comedy')
])

请注意,作为输入传递的记录必须对应于表格的形状:PostgreSQL不支持任意记录作为输入,因此您必须使用已知的记录类型。只需将未插入的列作为None传递,并且不要将它们包含在SELECT返回列表中。此方法也不允许您依赖DEFAULT,您必须明确指定每个插入的值。

答案 1 :(得分:0)

另一种一次插入许多行的方法(假设您不需要插入的ID)是使用copy_records_to_table方法。

data = [
    ("row", 1, "some data"),
    ("row", 2, "more data"),
]
await conn.copy_records_to_table('mytable', records=data)