Лучший способ вставить несколько строк с помощью asyncpg

Я хочу вставить несколько строк и получить идентификаторы обратно с помощью asyncpg, я нашел два способа: 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)

какой путь я должен предпочесть в случае 100x раз с 700 000 строк, или есть какой-то способ объединить этот подход? я полностью зеленый, так что бросай в меня несколько помидоров

2 ответа

Решение

Если вам нужно использовать RETURNING предложение для получения идентификаторов обратно, то следующий является наиболее эффективным способом вставки нескольких значений:

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, вы должны указать каждое вставленное значение явно.

asyncpg обеспечивает executemany способ вставить много строк.

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

Если вам нужно использовать RETURNING как вы позже упоминали, чтобы вернуть вставленные идентификаторы, этот ответ - путь.

Другой способ вставить много строк одновременно (при условии, что вам не нужны вставленные идентификаторы) - это использовать copy_records_to_table метод.

data = [
    ("row", 1, "some data"),
    ("row", 2, "more data"),
]
await conn.copy_records_to_table('mytable', records=data)
Другие вопросы по тегам