使用pandas+pymssql导入CSV到Azure SQL报TypeError的解决方法
问题根因
报错直接原因是pymssql的Cursor.execute()方法签名和pyodbc不同,仅接收2个位置参数:
- 待执行的SQL语句
- 所有待绑定参数组成的元组/列表
你当前写法把row.personID、row.PlayerName、row.Salary三个值作为独立的位置参数传入,加上SQL语句本身合计传入4个参数,直接触发参数数量不匹配的TypeError。
除此之外你的代码还存在3个会导致后续运行失败的隐患:
- pymssql默认不自动提交事务,就算参数修正,插入操作也会在连接关闭时回滚,数据不会实际写入表
- CSV中
Salary字段是带$符号、千分位逗号的字符串,若数据库对应字段为数值类型(MONEY/DECIMAL/INT),直接插入会触发类型转换错误 - 逐行调用
execute()配合iterrows()遍历插入效率极低,完全没必要用这种方式
可直接运行的修复代码
import pandas as pd import pymssql # 读取CSV文件 df = pd.read_csv("/Users/username/Documents/PowerBi/scraper/Players and Salaries.csv") # 清洗Salary字段:移除$、千分位逗号、首尾空格,转为整数 df["Salary"] = df["Salary"].str.replace("$", "", regex=False)\ .str.replace(",", "", regex=False)\ .str.strip()\ .astype(int) # 将DataFrame中的空值替换为None,对应数据库NULL值 df = df.where(pd.notnull(df), None) # 建立数据库连接 conn = pymssql.connect( server="sqlserver", database="dbtest", user="James", password="abES4grg3" ) cursor = conn.cursor() # 批量插入数据,性能远高于逐行单插 insert_sql = "INSERT INTO Players_Salaries (personID, PlayerName, Salary) VALUES (%s, %s, %s)" # 生成参数列表 data_params = list(df.itertuples(index=False, name=None)) cursor.executemany(insert_sql, data_params) # 提交事务,必须执行否则插入不生效 conn.commit() print(f"成功写入{cursor.rowcount}条球员薪资数据") # 关闭连接 conn.close()
关键说明
- pymssql的参数占位符统一用
%s,不区分字段类型,不要沿用pyodbc的?占位符,也不要用%d/%f这类数值占位符 - 批量插入用
executemany()代替逐行execute(),383条数据的插入速度会提升数十倍,数据量越大性能差距越明显 - 所有写操作完成后必须调用
conn.commit()提交事务,这是pymssql和很多自带自动提交的数据库客户端最大的区别之一 - 导入结构化数据到关系型数据库前必须做字段格式清洗,CSV读取的所有列默认都是字符串类型,和数据库字段类型不匹配时会触发各种隐式转换错误
内容的提问来源于stack exchange,提问作者DiegoV
相关产品推荐
相关产品推荐

