SQLAlchemy 2.0执行存储过程参数传递报错,求解决方案
解决SQLAlchemy 2.0 + pandas调用SQL Server存储过程的参数传递问题
错误原因分析
- 第一个异常
ArgumentError: List argument must consist only of tuples or dictionaries:使用SQLAlchemy 2.0的text对象后,pandas的params参数不再接受单个值的列表,要求为元组列表(批量执行场景)或单个字典(命名参数场景),原代码的[etf]不符合格式要求。 - 第二个异常
DBAPIError: COUNT field incorrect or syntax error:SQL语句中用?位置占位符,但params传的是带@前缀的字典键,两者不匹配导致参数计数错误。
正确解决方案
方案1:命名参数配合pandas read_sql_query
修改SQL语句为SQLAlchemy兼容的命名占位符(:参数名),同时params传递对应字典(键名不带@):
import sqlalchemy import pandas as pd sql_connection: str = "driver={ODBC Driver 17 for SQL Server};server=localhost\\SQLEXPRESS;database=Finance;trusted_connection=yes" sql_engine: sqlalchemy.engine.Engine = sqlalchemy.create_engine( url=sqlalchemy.engine.URL.create(drivername="mssql+pyodbc", query={"odbc_connect": sql_connection}) ) with sql_engine.connect() as connection: # 使用:etf作为命名占位符,映射SQL Server的@etf参数 query = sqlalchemy.text("EXEC dbo.get_latest_tickers @etf=:etf") # params传递不带@的字典键值对 return pd.read_sql_query(sql=query, con=connection, params={"etf": etf})
方案2:直接通过SQLAlchemy执行结果生成DataFrame
如果pandas的read_sql_query仍存在兼容问题,可直接用SQLAlchemy执行存储过程,再将结果转换为DataFrame:
import sqlalchemy import pandas as pd sql_connection: str = "driver={ODBC Driver 17 for SQL Server};server=localhost\\SQLEXPRESS;database=Finance;trusted_connection=yes" sql_engine: sqlalchemy.engine.Engine = sqlalchemy.create_engine( url=sqlalchemy.engine.URL.create(drivername="mssql+pyodbc", query={"odbc_connect": sql_connection}) ) with sql_engine.connect() as connection: query = sqlalchemy.text("EXEC dbo.get_latest_tickers @etf=:etf") # 直接执行查询并获取结果 result = connection.execute(query, {"etf": etf}) # 从结果集生成DataFrame,保留列名 return pd.DataFrame(result.fetchall(), columns=result.keys())
额外提示
- 字符串中的路径分隔符
\需转义为\\,或使用原始字符串r""(如r"server=localhost\SQLEXPRESS")避免转义问题。
内容的提问来源于stack exchange,提问作者scorpio
相关产品推荐
相关产品推荐

