【问题标题】:"Invalid parameter type" (numpy.int64) when inserting rows with executemany()使用 executemany() 插入行时出现“无效的参数类型”(numpy.int64)
【发布时间】:2017-06-17 20:31:06
【问题描述】:

我尝试将一堆数据插入数据库

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: ('无效的参数类型。param-index=4 param-type=numpy.int64', 'HY105')

减少到 100 个元组:

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

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

pyodbc.ProgrammingError: ('无效的参数类型。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' 不是可识别的 SET 选项。(195) (SQLExecDirectW)")

我是怎么解决这个问题的。

谢谢。

【问题讨论】:

    标签: python sql-server numpy pyodbc freetds


    【解决方案1】:

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

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

    会扔

    ProgrammingError: ('无效的参数类型。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 Server 没有任何意义。

    【讨论】:

    • 如何使用 Pandas DataFrame 做到这一点?我已经为每个 col 尝试了 df[col].astype(int) 但仍然没有乐趣。
    • @MattCamp - 我刚刚使用df.values.tolist() 尝试了一个简单的测试,它对我有用。如果您需要进一步的帮助,您应该ask a new question
    • 是的,我让它工作了.. 有一些问题是它不允许我提交数据帧,因为字段中不应该有重复项,然后当我尝试做更少的记录时它抛出上述错误..当我刚刚更改重复记录以测试它的工作时。谢谢
    • 当得到“无效的参数类型”错误时,有没有一个好的方法来判断是哪个值导致了错误?即当有大量列时,并不总是很明显哪一个导致错误...
    【解决方案2】:

    对于任何读到这篇文章的人来说,它把我逼疯了。

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

    【讨论】:

      【解决方案3】:

      我和罗伯特一样;我将所有内容都转换为字符串。就我而言,这是一个我将其转换为字符串类型的 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 文本数据。

      【讨论】:

        【解决方案4】:

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

        示例: 语法 - str()

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

        【讨论】:

          猜你喜欢
          • 2013-10-04
          • 1970-01-01
          • 1970-01-01
          • 2014-09-30
          • 2019-04-13
          • 1970-01-01
          • 2012-10-21
          • 2019-01-13
          • 1970-01-01
          相关资源
          最近更新 更多