使用 cursor.executemany(query, df.itertuples(index=False)) 的 pyodbc 批量数据导入挑战

Posted

技术标签:

【中文标题】使用 cursor.executemany(query, df.itertuples(index=False)) 的 pyodbc 批量数据导入挑战【英文标题】:pyodbc bulk data import challenge using cursor.executemany( query, df.itertuples(index=False) ) 【发布时间】:2019-05-24 16:22:00 【问题描述】:

我对 python 相当陌生,但我给了它一个严肃的 bash 来优雅地解决这个问题。

挑战:我想将市场数据从 pandas df 导入 sql 表。有大约 7000 种不同的股票,每一种都有大约 4000-10000 条日终记录,所以我试图让 pyodbc executemany 正常工作,而不是更新大量代码以使用 SQL Alchemy 和 to_sql 选项。

这几行代码给我带来了很大的挑战——需要更新 SQL ODBC Driver v17 以支持 index=False 选项。

SQL 目标表:

CREATE TABLE [dbo].[EOD](
    [Exchange] [varchar](10) NOT NULL,
    [Issue] [varchar](10) NOT NULL,
    [TDate] [date] NOT NULL,
    [O] [float] NOT NULL,
    [H] [float] NOT NULL,
    [L] [float] NOT NULL,
    [C] [float] NOT NULL,
    [V] [int] NOT NULL,
    [Split] [float] NULL
) ON [PRIMARY]
GO

数据: df.head()

         date exchange issue  open  high    low  close     volume  unadj
0  2016-11-14      ASX   CGC  2.96  2.97  2.880   2.90   549167.0    0.0
1  2016-11-15      ASX   CGC  2.90  2.96  2.865   2.95   587456.0    0.0
2  2016-11-16      ASX   CGC  2.96  2.96  2.890   2.94   666295.0    0.0
3  2016-11-17      ASX   CGC  2.94  3.15  2.910   3.11  1086692.0    0.0
4  2016-11-18      ASX   CGC  3.15  3.25  3.150   3.23  2043553.0    0.0

我得到的最接近的工作如下。但是,这种方法会导致:

('22007', '[22007] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]从字符串转换日期和/或时间时转换失败。(241) (SQLExecDirectW)')

cursor = cnxn.cursor()
query = ("INSERT INTO [Securities].[dbo].[EOD] (Exchange, Issue, TDate, O, H, L, C, V, Split) "
         "VALUES (?,?,?,?,?,?,?,?,?) " )
try:
    cursor.executemany( query, df.itertuples(index=False) )

except Exception as e:
    print(e)
cursor.close()

pandas 列已经是日期类型了——所以我不相信这是一个简单的日期类型转换(但无奈之下尝试了下面的转换)

query = ("INSERT INTO [Securities].[dbo].[EOD] (Exchange, Issue, TDate, O, H, L, C, V, Split) "
         "VALUES (convert(date,?,126),?,?,?,?,?,?,?,?) " )

任何关于如何使这种方法发挥作用的建议将不胜感激。

/卢瑟

【问题讨论】:

您的 DataFrame 的列排序为“date”、“exchange”、“issue”,但您的 INSERT 语句的列排序为“Exchange”、“Issue”、“TDate”。因此,您可能正在尝试将“问题”代码(“CGC”)插入“TDate”列。 OMG - 在花了很多时间学习如何做到这一点之后,我不得不靠近树木看不到森林。使用导致帖子的索引选项进行列更改......感觉很愚蠢。泰。 特别是关于使用itertuplesexecutemany,this GitHub issue 可能会感兴趣。 感谢 Gord - 那篇文章非常有用。每天学习更多关于 python 的知识。 【参考方案1】:

您的 DataFrame 的列顺序为“date”、“exchange”、“issue”,但您的 INSERT 语句的列顺序为“Exchange”、“Issue”、“TDate”。因此,您显然是在尝试将“问题”代码(“CGC”)插入“TDate”列。

更改 INSERT 语句的列顺序以匹配 DataFrame 中列的顺序。

【讨论】:

以上是关于使用 cursor.executemany(query, df.itertuples(index=False)) 的 pyodbc 批量数据导入挑战的主要内容,如果未能解决你的问题,请参考以下文章

在 python 中编写通用 cursor.executemany()

oracle_ cursor.executemany

MySQL 和 Python:Auto_Increment 不适用于 cursor.executemany()

pymssql executemany insert valueerror

大量行的 MySQLdb 错误的 executemany

如何使用 MySQL executemany 更新 Python 中的列表列表?