【问题标题】:Syntax Error while inserting bulk data from pandas df to postgresql将大容量数据从 pandas df 插入到 postgresql 时出现语法错误
【发布时间】:2020-09-13 03:21:13
【问题描述】:

我正在尝试将 pandas 数据帧数据批量插入 Postgresql。 在 Pandas 数据框中我有 35 列,在 Postgresql 表中我有 45 列。我从 pandas 数据框中选择 12 个匹配列并插入到 postgresql 表中。为此,我使用以下代码 sn-ps:

df = pd.read_excel(raw_file_path,sheet_name = 'Sheet1',usecols=col_names) <---col_names = list of desired columns (12 columns)
cols = ','.join(list(df.columns))
tuples = [tuple(x) for x in df.to_numpy()]
query = "INSERT INTO {0}.{1} ({2}) VALUES (%%s,%%s,%%s,%%s,%%s,%%s,%%s,%%s,%%s,%%s,%%s,%%s);".format(schema_name,table_name,cols)
curr = conn.cursor()
try:
    curr.executemany(query,tuples)
    conn.commit()
    curr.close()
except (Exception, psycopg2.DatabaseError) as error:
    print("Error: %s" % error)
    conn.rollback()
    curr.close()
    return 1
finally:
    if conn is not None:
        conn.close()
        print('Database connection closed.')

运行时出现此错误:

SyntaxError: syntax error at or near "%"
LINE 1: ...it,purchase_group,indenter_name,wbs_code) VALUES (%s,%s,%s,%...

即使我使用 ? 代替 %%s 我仍然收到此错误。

有人能解释一下吗?

附:我正在使用 Postgresql 版本 10。

【问题讨论】:

  • %s 将从 python 变量中获取字符串值。你想用那些 %s 的东西做什么?您已经使用 {0} 等将变量放入字符串中。您要传递 %s 还是在其中放置一些值?
  • @antont:我想将 %s 即行值作为元组传递到数据库中。目标是批量插入。或者即使我使用像"INSERT INTO {0}.{1} ({2})".format(schema_name,table_name,cols) + "VALUES(?,?,...?)" 这样的查询字符串,我也会遇到同样的错误。
  • 如果你想要更多参数,可以把 {3} {4} 等放在一起,我认为最好不要在一行中混合两种语法
  • 你为什么要加倍%
  • @parafit:我在某处看到使用 %%s。因此使用。

标签: python postgresql


【解决方案1】:

您现在所做的实际上是一次插入一个 pandas 数据帧。即使这行得通,这将是一个极其缓慢的操作。同时,如果数据可能包含字符串,只需将它们放入这样的查询字符串中,就会导致 SQL 注入。

我不会重新发明轮子。 Pandas 有一个to_sql 函数,它接受一个数据框并将其转换为您的查询。您可以指定发生冲突时的处理方式(当行已存在时)。

它适用于SQLAlchemy,它对 PostgreSQL 有很好的支持。即使它可能是一个需要探索和安装的新包,您也不需要在其他任何地方使用它来完成这项工作。

from sqlalchemy import create_engine
engine = create_engine('postgresql://localhost:5432/mydatabase')

pd.read_excel(
    raw_file_path,
    sheet_name = 'Sheet1',
    usecols=col_names  # <---col_names = list of desired columns (12 columns)
).to_sql(
    schema=schema_name,
    name=table_name,
    con=engine,
    method='multi'  # this makes it do all inserts in one go
)

【讨论】:

  • 这很好。但是,我一直在寻找更传统和通用的方法。
  • 您能解释一下您所说的“传统”是什么意思吗?我认为这是通用的,因为它得到了
  • 实际插入发生在哪里?
  • 在函数内部,它由 pandas 处理。请参阅我链接的文档以获取示例:他们调用该函数,然后 SELECT 并查看结果已插入
  • 谢谢鲁本!这行得通。只是有点好奇。使用create_engine时如何关闭连接?
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 2019-11-26
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 2019-11-26
  • 1970-01-01
相关资源
最近更新 更多