"Invalid parameter type" (numpy.int64) 使用 executemany() 插入行时

"Invalid parameter type" (numpy.int64) when inserting rows with executemany()

我尝试向数据库中插入一堆数据

insert_list = [(1,1,1,1,1,1),(2,2,2,2,2,2),(3,3,3,3,3,3),....] #up to 10000 tuples in this list

conn = pyodbc.connect('DRIVER={FreeTDS};SERVER=xxxxx;DATABASE=xxxx;UID=xx;PWD=xx;TDS_Version=7.0')
cursor = conn.cursor()

sql = "insert into ScanEMAxEMAHistoryDay(SecurityNumber, EMA1, EMA2, CrossType, DayCross, IsLocalMinMax) values (?, ?, ?, ?, ?, ?)"

cursor.executemany(sql, insert_list)

cursor.executemany(sql, insert_list)

pyodbc.ProgrammingError: ('Invalid parameter type. param-index=4 param-type=numpy.int64', 'HY105')

减少到 100 个元组:

cursor.executemany(sql, insert_list[:100])

cursor.executemany(sql, insert_list[:100])

pyodbc.ProgrammingError: ('Invalid parameter type. param-index=4 param-type=numpy.int64', 'HY105') cursor.executemany(sql, insert_list[:100])

减少到 5 个元组:

cursor.executemany(sql, insert_list[:5])
conn.commit()

这个可以插入数据库

我已经尝试:

sql = 'SET GLOBAL max_allowed_packet=50*1024*1024'
cursor.execute(sql)

在 excutemany() 之前,但它有一个错误:

pyodbc.ProgrammingError: ('42000', "[42000] [FreeTDS][SQL Server]'GLOBAL' is not a recognized SET option. (195) (SQLExecDirectW)")

我是怎么解决的。

谢谢。

您的问题不在于数据量 本身 ,而是您的一些元组包含 numpy.int64 不能直接用作参数值的值你的 SQL 声明。例如,

a = numpy.array([10, 11, 12], dtype=numpy.int64)
params = (1, 1, a[1], 1, 1, 1)
crsr.execute(sql, params)

会抛出

ProgrammingError: ('Invalid parameter type. param-index=2 param-type=numpy.int64', 'HY105')

因为第三个参数值是您的 numpy 数组 a 中的一个 numpy.int64 元素。使用 int() 转换该值将避免此问题:

a = numpy.array([10, 11, 12], dtype=numpy.int64)
params = (1, 1, int(a[1]), 1, 1, 1)
crsr.execute(sql, params)

顺便说一句,

的原因
sql = 'SET GLOBAL max_allowed_packet=50*1024*1024'
cursor.execute(sql)

没用是因为 max_allowed_packet 是一个 MySQL 设置,对 Microsoft SQL 服务器没有任何意义。

对于任何读到这篇文章的人来说,它让我感到困惑。

我最终的解决方案是将所有变量转换为 'str' 并且效果很好。

我和罗伯特一样;我将所有内容都转换为字符串。在我的例子中,它是我转换为字符串类型的 pandas 数据框:

data = pandas.read_json(...)
data.astype(str).to_sql(...)

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.astype.html

如果您检索的数据包含 URL,您可能会收到“未知协议”错误(或类似错误)。如果在转换为字符串类型后仍出现此错误,请尝试使用 StringIO 而不是 :

import requests
from io import StringIO
...
data = pandas.read_json(StringIO(response.text))

其中 responserequests 库中对象 Response 的实例,其属性 text 包含 json 文本数据。

我在使用 pyodbc 将参数传递到 SQL INSERT 语句时遇到了同样的错误。正如罗伯特所提到的,只需将变量转换为字符串即可。

示例: 语法 - str()

cursor.execute("INSERT INTO Table ([col1],[col2],[col3]...])VALUES(?,'test',?)", str(value1), str(value3))