使用Pandas导入Parquet数据到SQL Server时遇cursor.execute错误求助
问题解决:Parquet数据加载到SQL Server的两个错误修复
错误原因分析
第一个错误(Series布尔值歧义)
直接将pandas的Series对象(循环中的row)传给cursor.execute(),pymssql在解析参数时尝试判断Series的布尔值,触发pandas的歧义错误——Series是多值对象,无法直接判断真假。第二个错误(占位符语法错误)
pymssql使用%s作为参数占位符,而非?,用?会被SQL Server识别为语法错误。
修复步骤及优化代码
关键修改点:
- 将占位符从
?替换为%s - 将每行数据转换为元组(pymssql可直接解析的序列类型)
- 提前批量处理datetime列,避免循环内逐行操作
- 用批量插入替代逐行插入,提升效率
- 替换
iterrows为itertuples,加快行数据获取速度
完整修复代码
import pymssql import pandas as pd import duckdb # 读取Parquet文件(路径用原始字符串避免转义问题) parquet_file_path = r"C:\path\pp2.snappy.parquet" df = pd.read_parquet(parquet_file_path) # 统一填充空值 df = df.fillna(0) # 获取列名与pymssql兼容的占位符 columns = df.columns.tolist() column_names = ', '.join(columns) placeholders = ', '.join(['%s'] * len(columns)) # 替换为%s占位符 # 识别并批量处理datetime列 datetime_columns = [] df_schema = duckdb.sql(f"describe select * from read_parquet('{parquet_file_path}')").df() for col_name, col_type in zip(df_schema["column_name"], df_schema["column_type"]): if "TIMESTAMP" in col_type: datetime_columns.append(col_name) # 批量转换datetime类型,空值替换为默认时间 for dt_col in datetime_columns: df[dt_col] = pd.to_datetime(df[dt_col], errors='coerce').fillna(pd.Timestamp('1970-01-01 00:00:00')) # 连接SQL Server(补充你的连接信息) conn = pymssql.connect( server='your_server_address', user='your_username', password='your_password', database='your_database' ) cursor = conn.cursor() # 生成插入语句 insert_query = f""" INSERT INTO dbo.table_name ({column_names}) VALUES ({placeholders}) """ # 转换所有行为元组列表,用executemany批量插入 rows_to_insert = [tuple(row) for row in df.itertuples(index=False)] # 执行插入并处理事务 try: cursor.executemany(insert_query, rows_to_insert) conn.commit() print("数据插入成功") except Exception as e: conn.rollback() print(f"插入失败:{str(e)}") finally: cursor.close() conn.close()
额外说明
- 批量插入优化:
executemany比循环execute效率提升数倍,适合大数据量场景 - 事务保障:添加try-except-finally块,异常时回滚事务,避免数据不一致
- 路径处理:用原始字符串
r"..."处理文件路径,避免转义字符引发的问题 - 连接参数:需替换为你的SQL Server实际连接信息
内容的提问来源于stack exchange,提问作者Poreddy Siva Sukumar Reddy US
相关产品推荐
相关产品推荐

