【问题标题】:Best way to insert multiple rows with asyncpg使用 asyncpg 插入多行的最佳方法
【发布时间】:2017-09-30 01:12:15
【问题描述】:

我想插入多行并使用 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循环中使用准备好的语句

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)

如果 100 倍 700 000 行,我必须更喜欢哪种方式,或者有什么方法可以结合这些方法? 我完全是绿色的,所以给我扔一些西红柿

【问题讨论】:

标签: python postgresql python-asyncio asyncpg


【解决方案1】:

asyncpg 提供了executemany 方法来插入多行。

statement = """INSERT INTO films (code,
                           title, 
                           did, 
                           date_prod, 
                           kind) VALUES($1, $2, $3, $4, $5);"""
await connection.executemany(statement, values)

如果您需要使用后面提到的RETURNING 来返回插入的 id,则此answer 是要走的路。

【讨论】:

  • thnx 为正确的标签。由于您的回答,我编辑了问题 - 添加“RETURNINNG”子句 - 所以“executemany”现在不符合要求,抱歉误导。
【解决方案2】:

如果需要使用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,您必须明确指定每个插入的值。

【讨论】:

  • 稍微注意一下,“输入必须与表格的形状相对应”是相当危险的。表的形状、列的顺序(使用 psql 中的 \d 验证)可能因一个 PG 服务器而异,这使得您的代码严重依赖于在每个数据库实例上创建表的方式。
【解决方案3】:

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

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

【讨论】:

  • 事实证明这对我来说是最方便的方式:我有一批按表名分组的记录,并且它们的列已经按正确的顺序排列。
  • ...虽然,我需要“ON CONFLICT ... UPDATE ...”,所以我不确定我能否使用这种机制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-24
相关资源
最近更新 更多