Получение имен полей в двойных кавычках и разделенных запятой при передаче как * args в соединение psycopg2 - PullRequest
0 голосов
/ 04 мая 2020

Контекст

Я пытаюсь обновить / вставить базу данных PostgreSQL с содержимым pandas DataFrame используя psycopg2 .

Я повторяю строки DataFrame, потому что мы не можем использовать метод .to_sql() при использовании оператора UPSERT .

Short

То, что я пытаюсь сделать, это развернуть имена столбцов и их значения в строку запроса SQL с выражениями, отмеченными звездочкой, для имен столбцов и фактические значения.

Все работает нормально, за исключением двух мелких неловких деталей;

  1. имена и значения столбцов разделяются не запятой, а пробелом,
  2. имена столбцов заключаются в одинарные кавычки, отсюда и ошибка.


Код, сведения и сообщение об ошибке:

Вот фрагмент кода, который я использую;

# Python 3.6.9 (default, Apr 18 2020, 01:56:04)
import pandas as pd # -- version 1.0.3
import psycopg2     # -- version 2.8.5 (dt dec pq3 ext lo64)

df = pd.DataFrame({'__col1__name_': [1],
  '__col3__name_': [2],
  '__col3__name_': ['three'],
  '__col4__name_': [4],
  '_col5_name_': [5],
  '_col6_name_': [6],
  '_col7_name_': [7.0],
  '_col8_name_': [8.0],
})

cols      = list(df.columns)
nCols     = len(cols)
name      = "tablename"
for i, row in df.iterrows():
    # Warning: ugly query here, but I want it as compact as possible
    # and I need to pass the table name as an argument because I'm actually running this 
    # in a for loop over some tables which may change in the future, so I don't want 
    # to patch the code much each time a column is renamed or added to the database.
    query = """
        INSERT INTO """+"schema.{}".format(name)+"""
        ("""+nCols*'%s '+""")
        VALUES ("""+nCols* '%s ' +""")
        ON CONFLICT (%s) DO UPDATE SET
        ("""+(nCols)*'%s '+""") = ("""+(nCols)*'%s '+""")
        WHERE %s = %s
        """
    with psycopg2.connect(**DB_PARAMS) as conn:
        with conn.cursor() as curs:
            print(curs.mogrify(sql_query, ((*cols, *row, cols[0], *cols, *row, cols[0], row[0]))))
            curs.execute(sql_query, ((*cols, *row, cols[0], *cols, *row, cols[0], row[0])))

И я получаю это SyntaxError :

SyntaxError: syntax error at or near "'__col1__name_'"
LINE 3:         ('__col1__name_' '__col3__name_' '__col4__name_' '_c..
                 ^

У меня такая же ошибка, если я копирую и вставляю вывод mogrify непосредственно в pgAdmin , например.

Вывод Mogrify выглядит следующим образом:

INSERT INTO schema.tablename
        ('__col1__name_' '__col3__name_' '__col4__name_' '_col5_name_' '_col6_name_' '_col7_name_' '_col8_name_' )
        VALUES (1 'three' 4 5 6 7.0 8.0 )
        ON CONFLICT ('__col1__name_') DO UPDATE SET
        ('__col1__name_' '__col3__name_' '__col4__name_' '_col5_name_' '_col6_name_' '_col7_name_' '_col8_name_' ) = (1 'three' 4 5 6 7.0 8.0 )
        WHERE '__col1__name_' = 1

Это не работает в Postgres из-за одинарной кавычки.

Я действительно стараюсь не составлять строку запроса SQL с .format() (за исключением table name) перед отправкой на curs.execute(), но пусть psycopg2 обрабатывает аргументы за меня, что, как мне сказали, является хорошей идеей.


Question

Как я могу заключить имена столбцов в двойные кавычки и разделить их запятой?
То же самое для значений; они не разделяются запятой.

...