Вставка нескольких строк с помощью psycopg2

Согласно psycopg2: вставьте несколько строк одним запросом, это гораздо более эффективно использовать execute psycopg2 вместо executemany . Другие могут подтвердить?

Приведенный выше вопрос StackOverflow предлагает использовать mogrify для создания утверждений типа:

INSERT INTO table VALUES (value1, value2), (value3, value4)

Можно ли сгенерировать такой оператор с помощью обычной функции execute? Я думал что-то в форме

cursor.execute("""INSERT INTO table VALUES (%s, %s), (%s, %s)""", ((value1,value2),(value3,value4)))

должно сработать.

ОБНОВИТЬ:

Например, я попытался перейти к выполнению инструкции sql:

insert into history (timestamp) values (%s),(%s); 

со следующим кортежем:

(('2014-04-27 14:07:30.000000',), ('2014-04-27 14:07:35.000000',))

но все, что я получил, было ошибкой:

нет результатов для получения


person ChaimKut    schedule 27.04.2014    source источник
comment
Вы не пробовали это первым?   -  person Martijn Pieters    schedule 27.04.2014
comment
Многозначные вставки действительно более эффективны, чем executemany в psycopg2, хотя и только до определенного момента — если вы вставляете десятки тысяч строк на оператор, использование памяти становится проблемой. Партии в несколько сотен или пару тысяч (если ряды меньше) могут подойти.   -  person Craig Ringer    schedule 27.04.2014


Ответы (1)


Чтобы использовать метод execute, поместите вставляемые данные в список. Список будет адаптирован psycopg2 к массиву. Затем вы отключаете массив и присваиваете значения по мере необходимости.

import psycopg2

insert = """
    insert into history ("timestamp")
    select value
    from unnest(%s) s(value timestamp)
    returning *
;"""

data = [('2014-04-27 14:07:30.000000',), ('2014-04-27 14:07:35.000000',)]
conn = psycopg2.connect("host=localhost4 port=5432 dbname=cpn")
cursor = conn.cursor()
cursor.execute(insert, (data,))
print cursor.fetchall()
conn.commit()
conn.close()

Не уверен, что разница в производительности с executemany будет существенной. Но я думаю, что вышеизложенное более аккуратно. Предложение returning, как следует из названия, возвращает вставленные кортежи.

Кстати, timestamp — это зарезервированное слово, и его не следует использовать в качестве имени столбца.

person Clodoaldo Neto    schedule 27.04.2014
comment
+1 за «не вложенность» и указание на проблему «отметки времени», остаток использования ORM. - person ChaimKut; 27.04.2014
comment
(В postgres похоже, что временная метка не зарезервирована. postgresql .org/docs/9.3/static/sql-keywords-appendix.html ) - person ChaimKut; 27.04.2014
comment
Вам не нужны имена столбцов в select. Это будет работать так же хорошо: INSERT INTO my_table (col1, col2) SELECT * FROM unnest(%s) s(col1 integer, col2 text) RETURNING *; - person pir; 20.09.2019