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

如何正确使用pd.read_sql带参数查询SQL Server?

问题原因与解决方案

这个问题其实是对参数化查询的作用范围理解有误——参数化查询里的params参数是用来传递数据值的(比如WHERE id = ?里的id值),而不是用来替换SQL中的标识符(列名、表名、函数名这类数据库对象名称)的。

为什么会得到重复的字段名?

当你执行query = 'SELECT ?,? FROM position_names'并传入params = ['position_id','position_name']时,SQL Server会把这两个参数当作字符串常量来处理,相当于实际执行的SQL是:

SELECT 'position_id', 'position_name' FROM position_names

这就意味着,表的每一行都会返回'position_id'和'position_name'这两个固定字符串,所以你看到的结果全是重复的字段名,而不是列对应的数据。

正确的动态列名查询方式

如果需要动态指定查询的列,你需要安全地拼接SQL语句,但直接拼接字符串有SQL注入风险,所以一定要先验证传入的列名是否是目标表中存在的合法列:

  1. 先获取目标表的合法列名列表:
# 查询position_names表的所有合法列
valid_columns = pd.read_sql(
    "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'position_names'",
    engine
)['COLUMN_NAME'].tolist()
  1. 验证你要查询的列是否合法,再拼接SQL:
target_columns = ['position_id', 'position_name']

# 检查所有目标列都在合法列表中
if all(col in valid_columns for col in target_columns):
    # 拼接列名到SQL中
    query = f"SELECT {', '.join(target_columns)} FROM position_names"
    # 执行查询
    result = pd.read_sql(query, engine)
else:
    raise ValueError("传入的列名包含非法字段,可能存在SQL注入风险")

这种方式既满足了动态选择列的需求,又通过列名验证避免了SQL注入的安全问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:32:20