首页 > 解决方案 > 出现错误:ValueError:不支持的格式字符:'('

问题描述

我有以下函数用于动态生成 SQL 查询以使用 psycopg2 在 postgres 中插入熊猫数据帧。我将使用此函数插入​​多个数据帧,这些数据帧可能没有数据库中的所有列,因此我不使用 pandas.to_sql()。我不断收到错误ValueError: unsupported format character: '(',无法弄清楚是什么原因造成的。

任何帮助,将不胜感激。

def execute_values(conn, df, schema, table):
    """
    Using psycopg2.extras.execute_values() to insert the dataframe
    """
    
    # Create a tuple of dicts from the dataframe values
    dicts = tuple(df.to_dict('records'))

    columns = sql.SQL(',').join(map(sql.Identifier, list(df.columns)))
    values = sql.SQL(',').join(map(sql.Placeholder, list(df.columns)))

    # SQL query to execute
    query = sql.SQL('INSERT INTO {} ({}) VALUES ({})').format(
        sql.Identifier(schema, table),
        columns,
        values
    )
    
    cursor = conn.cursor()
    try:
        extras.execute_values(cursor, query, dicts)
        conn.commit()
    except (Exception, psycopg2.DatabaseError) as error:
        print("Error: %s" % error)
        conn.rollback()
        cursor.close()
        raise

    print("execute_values() done")
    cursor.close() 

标签: postgresqlpsycopg2

解决方案


如何使用以下方法制作动态 SQL execute_values

import psycopg2
from psycopg2.extras import execute_values
from psycopg2 import sql

con = psycopg2.connect("dbname=test host=localhost user=aklaver")
cur = con.cursor()

columns = sql.SQL(',').join(map(sql.Identifier, ['id', 'cond', 'animal']))

data_dict = [{"id": 20, "cond": "fair", "animal": "fish"}, {"id": 30, "cond": "poor", "animal": "fish"}, {"id": 40, "cond": "great", "animal": "fish"}]


values = sql.SQL(',').join(map(sql.Placeholder, ['id', 'cond', 'animal']))
# Since you are using a dict you need to provide a template for 
# execute_values
values_template = sql.SQL('(') + values + sql.SQL(')')

print(values_template.as_string(con))                                                                                                                                     (%(id)s,%(cond)s,%(animal)s)


insert_sql = sql.SQL("INSERT INTO {} ({}) VALUES %s").format(sql.Identifier("animals"), columns)

print(insert_sql.as_string(con))
INSERT INTO "animals" ("id","cond","animal") VALUES %s

execute_values(cur, insert_sql, data_dict, template=values_template)
con.commit()

 select * from animals ;
 id | cond  | animal 
----+-------+--------
 20 | fair  | fish
 30 | poor  | fish
 40 | great | fish


推荐阅读