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

使用pyodbc调用含UDT参数的存储过程时出错

解决pyodbc调用带表值参数的存储过程报错问题

报错pyodbc.ProgrammingError: ('Invalid parameter type. param-index=4 param-type=NAType', 'HY105')的核心原因是pyodbc无法直接识别列表元组作为SQL Server表值参数(UDT),同时日期字符串未转换为对应的数据类型。以下是修正方案:

关键修正点

  • 必须使用pyodbc.TableValuedParameter显式封装表值参数,指定对应的SQL Server用户定义表类型名称
  • 将DataFrame中的日期字符串转换为Pythondatetime对象,匹配SQL ServerDATETIME2类型要求
  • 确保DataFrame的列顺序与DemandType的列定义完全一致

修正后的代码

import pyodbc
import pandas as pd
from datetime import datetime

def uploadDataframeToSQL(inputData: pd.DataFrame):
    # 转换日期列:字符串转datetime对象
    inputData['eptTimeStamp'] = pd.to_datetime(inputData['eptTimeStamp'])
    
    conn_str = (
        "DRIVER={ODBC Driver 17 for SQL Server};"
        "SERVER=<my_db_url>;"
        "DATABASE=<my_db>;"
        "UID=<my_uid>;"
        "PWD=<my_pwd>"
    )
    conn = pyodbc.connect(conn_str)
    cursor = conn.cursor()
    
    # 转换为元组列表(确保列顺序与DemandType一致)
    data_to_insert = [tuple(row) for index, row in inputData.iterrows()]
    
    # 用TableValuedParameter封装表值参数,指定UDT类型名
    tvp = pyodbc.TableValuedParameter('dbo.DemandType', data_to_insert)
    
    # 执行存储过程
    cursor.execute('EXEC dbo.MergeDemandUpsert @Demand=?', (tvp,))

    conn.commit()
    cursor.close()
    conn.close()

额外注意事项

  1. 确认DataFrame的列顺序严格对应DemandType的定义:eptTimeStamp、amount、mid、peak、mid2、peak2、Total,表值参数是按位置匹配列,而非列名
  2. 确保ODBC Driver 17 for SQL Server已正确安装,该版本支持表值参数的完整功能
  3. 如果DataFrame中存在空值(NaN),需转换为None,对应SQL Server的NULL值(可通过inputData = inputData.where(pd.notnull(inputData), None)处理)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:48:20