to_sql pyodbc count字段不正确或语法错误

时间:2018-06-04 21:32:56

标签: python sql-server pandas pyodbc

我正在从api网站下载Json数据并使用sqlalchemy,pyodbc和pandas' to_sql函数将该数据插入MSSQL服务器。

我最多可以下载10000行,但是我必须将chunksize限制为10,否则会出现以下错误:

  

DBAPIError:(pyodbc.Error)(' 07002',' [07002] [Microsoft] [SQL Server   Native Client 11.0] COUNT字段不正确或语法错误(0)   (SQLExecDirectW)')[SQL:' INSERT INTO [TEMP_producing_entity_details]

要下载大约5亿行,它只是以这种速度爬行。有关解决方法的任何建议吗?

谢谢,

3 个答案:

答案 0 :(得分:8)

更新:

pandas 0.23.1已经恢复了0.23.0中引入的有问题的变化。但是,原始性能的最佳解决方案仍然是CSV - > bcp方法如下所述。

更新:

pandas 0.24.0显然已经重新引入了这个问题(参考:here

(原始答案)

在pandas版本0.23.0之前,to_sql会为DataTable中的每一行生成一个单独的INSERT:

exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    0,N'row000'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    1,N'row001'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    2,N'row002'

大概为了提高性能,pandas 0.23.0现在生成一个表值构造函数,每次调用插入多行

exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6),@P3 int,@P4 nvarchar(6),@P5 int,@P6 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2), (@P3, @P4), (@P5, @P6)',
    0,N'row000',1,N'row001',2,N'row002'

问题是SQL Server存储过程(包括sp_prepexec等系统存储过程)限制为2100个参数,因此如果DataFrame有100列,那么to_sql只能插入约20行时间。

我们可以使用

计算所需的chunksize
# df is an existing DataFrame
#
# limit based on sp_prepexec parameter count
tsql_chunksize = 2097 // len(df.columns)
# cap at 1000 (limit for number of rows inserted by table-value constructor)
tsql_chunksize = 1000 if tsql_chunksize > 1000 else tsql_chunksize
#
df.to_sql('tablename', engine, if_exists='replace', index=False, chunksize=tsql_chunksize)

然而,最快的方法仍然可能是:

  • 将DataFrame转储到CSV文件(或类似文件),然后

  • 让Python调用SQL Server bcp实用程序将该文件上传到表中。

答案 1 :(得分:0)

根据Gord Thompson的回答进行了一些修改。这将自动计算块大小并将其保持为最接近的最小整数值,该值适合2100参数限制:

--cpus=

答案 2 :(得分:0)

没有名望,所以我无法对Amit S发表评论。 我只是尝试过这种方法,将chuknum的方法设置为“ multi” 仍然显示错误:

[Microsoft][SQL Server Native Client 11.0][SQL Server]传入请求的参数太多。该服务器最多支持2100个参数。减少参数数量并重新发送请求

所以我刚刚修改了

chunknum=math.floor(2100/df_num_of_cols) 

chunknum=math.floor(2100/df_num_of_cols) - 1

现在看来工作正常。 我认为应该是一些边缘问题...