You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python程序SQL Insert命令在不同pyodbc版本下执行失败求助

问题描述

我编写了一个Python程序,通过Insert语句向SQL Server导入数据。在本地PC使用pyodbc 4.0.0版本时运行正常,但在UNIX服务器上使用pyodbc 4.0.26版本执行Insert时失败,抛出以下错误:

pyodbc.Error: ('07006', '[07006][Openlink][ODBC][Driver]Restricted datatype attribute violation (0)(SQLBindparameter)')

执行Insert前的DELETE语句可正常清空表数据,相关代码如下:

cursor.execute("DELETE FROM [dbo].[Python_Table]")

f.write("deleted rows from Python Table")
f.write("\n====================\n")
db.commit()   
for index, row in df.iterrows():
    cursor.execute("INSERT INTO dbo.Python_Table ([ID], [Compliant_Ind], [Mappings], [Govt_Req_1_Ind], [Govt_Req_2_Ind], [GLBA_Req_3_Ind],[GLBA_Req_4_Ind],[GLBA_Req_5_Ind], [Enterprise_Issue],  [Classification_Date], [Comments], [Load_Date]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)", row['ID'], row['Compliant_Ind'], row['Mappings'], row['Govt_Req_1_Ind'], row['Govt_Req_2_Ind'],row['Govt_Req_3_Ind'],row['Govt_Req_4_Ind'],row['Govt_Req_5_Ind'], row['Enterprise_Issue'], row['Classification_Date'], row['Comments'],row['load_date'])      

    db.commit()

格式化后的Insert语句:

"INSERT INTO dbo.Python_Table (
    [ID], 
    [Compliant_Ind], 
    [Mappings], 
    [Govt_Req_1_Ind], 
    [Govt_Req_2_Ind], 
    [GLBA_Req_3_Ind],
    [GLBA_Req_4_Ind],
    [GLBA_Req_5_Ind], 
    [Enterprise_Issue],  
    [Classification_Date], 
    [Comments], 
    [Load_Date]) 
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", 
    row['ID'], 
    row['Compliant_Ind'], 
    row['Mappings'], 
    row['Govt_Req_1_Ind'], 
    row['Govt_Req_2_Ind'],
    row['Govt_Req_3_Ind'],
    row['Govt_Req_4_Ind'],
    row['Govt_Req_5_Ind'], 
    row['Enterprise_Issue'], 
    row['Classification_Date'], 
    row['Comments'],
    row['load_date']
解决思路

1. 核对数据类型兼容性

这个错误核心原因是Python数据类型与SQL Server列类型不匹配,pyodbc新版本对类型绑定的校验更严格:

  • 逐个匹配DataFrame字段与SQL表Python_Table的列类型:
    • 日期类型列(如Classification_Date、Load_Date):确保DataFrame中是Python原生datetime对象,而非numpy.datetime64或字符串,可通过pd.to_datetime()转换后再插入。
    • 布尔标识列(如Compliant_Ind系列字段):若SQL Server列是bit类型,需保证DataFrame中的值是Pythonbool类型,而非int或字符串。
    • 字符串列:检查是否存在内容长度超过SQL列定义长度的情况,新版本对长度限制的校验更严格。

2. 显式指定参数绑定类型

pyodbc新版本可能调整了默认参数绑定逻辑,显式指定类型可避免自动转换错误:

import pyodbc

# 整理参数列表
params = (
    row['ID'], 
    row['Compliant_Ind'], 
    row['Mappings'], 
    row['Govt_Req_1_Ind'], 
    row['Govt_Req_2_Ind'],
    row['Govt_Req_3_Ind'],
    row['Govt_Req_4_Ind'],
    row['Govt_Req_5_Ind'], 
    row['Enterprise_Issue'], 
    row['Classification_Date'], 
    row['Comments'],
    row['load_date']
)

# 对应SQL Server列的参数类型(需根据实际表结构调整)
param_types = [
    pyodbc.SQL_INTEGER,
    pyodbc.SQL_BIT,
    pyodbc.SQL_VARCHAR,
    pyodbc.SQL_BIT,
    pyodbc.SQL_BIT,
    pyodbc.SQL_BIT,
    pyodbc.SQL_BIT,
    pyodbc.SQL_BIT,
    pyodbc.SQL_VARCHAR,
    pyodbc.SQL_DATETIME,
    pyodbc.SQL_VARCHAR,
    pyodbc.SQL_DATETIME
]

# 绑定参数类型后执行插入
cursor.setinputsizes(*param_types)
cursor.execute(insert_sql, params)

3. 排查ODBC驱动差异

UNIX服务器使用的Openlink ODBC驱动,与本地Windows常用的微软官方ODBC驱动行为可能存在差异:

  • 更新Openlink ODBC驱动至最新版本,修复可能存在的类型绑定兼容性问题。
  • 替换为微软官方的MS ODBC Driver for SQL Server(Linux版),该驱动与pyodbc新版本的兼容性更稳定。

4. 改用批量插入替代逐行插入

逐行插入不仅效率低,还容易触发类型绑定问题,改用executemany()或pandas.to_sql()优化:

用executemany批量插入

# 整理所有数据为列表
data_list = []
for index, row in df.iterrows():
    data_list.append((
        row['ID'], 
        row['Compliant_Ind'], 
        row['Mappings'], 
        row['Govt_Req_1_Ind'], 
        row['Govt_Req_2_Ind'],
        row['Govt_Req_3_Ind'],
        row['Govt_Req_4_Ind'],
        row['Govt_Req_5_Ind'], 
        row['Enterprise_Issue'], 
        row['Classification_Date'], 
        row['Comments'],
        row['load_date']
    ))

# 批量执行插入
insert_sql = "INSERT INTO dbo.Python_Table ([ID], [Compliant_Ind], [Mappings], [Govt_Req_1_Ind], [Govt_Req_2_Ind], [GLBA_Req_3_Ind],[GLBA_Req_4_Ind],[GLBA_Req_5_Ind], [Enterprise_Issue],  [Classification_Date], [Comments], [Load_Date]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)"
cursor.executemany(insert_sql, data_list)
db.commit()

用pandas.to_sql直接插入

# 注意:需确保DataFrame列名与SQL表列名大小写一致(UNIX系统大小写敏感)
df.rename(columns={'load_date': 'Load_Date'}, inplace=True)
df.to_sql('Python_Table', con=db, schema='dbo', if_exists='append', index=False)

5. 检查字段名大小写一致性

UNIX系统大小写敏感,代码中row['load_date']与SQL表列[Load_Date]大小写不一致,可能导致驱动解析异常。建议统一列名大小写,比如将DataFrame列名改为Load_Date后再插入。

内容的提问来源于stack exchange,提问作者user19210181

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:35:14