使用Python将.xls DataFrame插入SQL Server表时遇类型错误求助
我正尝试使用pandas和pyodbc库,将从.xls文件读取的Python DataFrame插入SQL Server Management Studio中的现有表,但遇到以下错误:
Traceback (most recent call last):
File "c:/Python/Task1.py", line 27, in cursor.execute('''
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 16 (""): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision. (8023) (SQLExecDirectW)')
以下是我的Python脚本:
import pandas as pd import pyodbc #Import the CSV File into the DataFrame data = pd.read_excel (r'C:\Users\Diego\Documents\1.Laboral\Jas-Ole\Revenue Management\Reservation_stats_REF.xls') df = pd.DataFrame(data, columns= ['Confirmation_number','Status','Name','Telephone','Adults','Children','Baby', 'Start_date','End_date','Stays','Reservation_date','Property','Covid_payment','Charged_amount','Revenue','Email', 'Origin','Market_code','Transport']) #Connect Python to SQL Server conn = pyodbc.connect('Driver={SQL Server};' 'Server=DIEGO\SQLEXPRESS;' 'Database=Auxiliary;' 'Trusted_Connection=yes;') cursor = conn.cursor() #Delete a Table data in SQL Server using Python for row in df.itertuples(): cursor.execute(''' DELETE FROM Auxiliary.dbo.Res_statsTEMP ''') #Insert DataFrame to Table for row in df.itertuples(): cursor.execute(''' INSERT INTO Auxiliary.dbo.Res_statsTEMP (Confirmation_number,Status,Name,Telephone,Adults, Children,Baby,Start_date,End_date,Stays,Reservation_date,Property,Covid_payment,Charged_amount, Revenue,Email,Origin,Market_code,Transport) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ''', row.Confirmation_number, row.Status, row.Name, row.Telephone, row.Adults, row.Children, row.Baby, row.Start_date, row.End_date, row.Stays, row.Reservation_date, row.Property, row.Covid_payment, row.Charged_amount, row.Revenue, row.Email, row.Origin, row.Market_code, row.Transport ) conn.commit()
希望能协助解决此问题,提前感谢。
先帮你拆解下这个错误:提示里明确说第16个参数对应的值不是有效的float类型。对应你INSERT语句的参数顺序数一下,第16个参数是row.Email——这明显不对劲,Email应该是字符串类型,说明要么是你的SQL表列定义出了问题,要么是列顺序错位导致类型不匹配。下面给你一步步排查和解决的方法:
1. 核对SQL表结构与代码列顺序
先打开SSMS查看Auxiliary.dbo.Res_statsTEMP的表结构:
- 确认
Adults、Children、Charged_amount这类数值列的类型是int或float - 确认
Email、Name这类文本列的类型是varchar/nvarchar
然后对比你Python代码中INSERT的列顺序和VALUES的参数顺序,必须完全一一对应——哪怕只错一列,都会出现这种类型不匹配的错误。
2. 检查DataFrame数值列的无效值
错误提示还提到要检查源数据的无效值,比如数值精度异常。你可以用pandas快速排查:
# 查看数值列的数据类型 print(df[['Adults','Children','Baby','Stays','Charged_amount','Revenue']].dtypes) # 找出Adults列中非数值的行 print(df[pd.to_numeric(df['Adults'], errors='coerce').isna()])
如果发现有非数值内容(比如空字符串、特殊符号),可以先做数据清洗:
# 把无效值转为0,或者根据业务逻辑填充/删除 df['Adults'] = pd.to_numeric(df['Adults'], errors='coerce').fillna(0).astype(int)
3. 优化删除数据的逻辑(额外建议)
你现在的删除逻辑是循环每一行都执行一次DELETE,这会重复清空表N次(N是DataFrame行数),完全没必要,改成一次性执行即可:
cursor.execute('DELETE FROM Auxiliary.dbo.Res_statsTEMP') conn.commit() # 别忘了提交删除操作
4. 用to_sql简化插入操作
比起手动写INSERT循环,pandas的to_sql方法能自动处理大部分类型映射问题,更高效也更少出错:
from sqlalchemy import create_engine # 先安装sqlalchemy:pip install sqlalchemy engine = create_engine('mssql+pyodbc://DIEGO\SQLEXPRESS/Auxiliary?driver=SQL+Server+Native+Client+11.0&trusted_connection=yes') # 清空表 with engine.connect() as conn: conn.execute('DELETE FROM Res_statsTEMP') conn.commit() # 插入数据 df.to_sql('Res_statsTEMP', engine, schema='dbo', if_exists='append', index=False)
优先排查列顺序和表结构的匹配问题,这是这类错误最常见的诱因,祝你顺利解决~
内容的提问来源于stack exchange,提问作者Diego

