首页 > 解决方案 > 如何在 pandas.read_sql_query 中将变量传递给 MySQL 查询的 IN 子句?

问题描述

我正在编写一个通用函数来查询我想使用 *args 来获取值的数据库。这是功能

def get_latest_value(col_name, *args):
    query = "select * from latest_value where {column} in (%s)"
    query = query.format(**dict(column=col_name))
    results = pd.read_sql_query(query, engine, params = [args])
    return(results)

但是,当我运行它时,我收到此错误:

ProgrammingError: (MySQLdb._exceptions.ProgrammingError) not all arguments converted during bytes formatting
[SQL: select * from latest_value where amfi_code in (%s)]
[parameters: (100370, 100371)]
(Background on this error at: http://sqlalche.me/e/f405)

我什至尝试在传递 *args 之前将其转换为列表,但这也无济于事。

无法弄清楚如何将 *args 中的值传递给 IN 子句。任何帮助表示赞赏。

此外,使用字符串连接作为列名是否可以避免 sql 注入攻击?

更新:

我将代码更改如下:

def get_latest_value(col_name, *args):
    query = "select * from latest_value where {column} in (%s)"
    query = query.format(**dict(column=col_name))
    conditions = ", ".join(map(str, args))
    results = pd.read_sql_query(query, engine, params = [conditions])
    return(results)

我现在没有收到错误,但我只得到 args 中第一个值的结果。

标签: pythonmysqlpandas

解决方案


我无法弄清楚到底是什么,但我认为 sqlalchemy 在处理这种情况时存在问题。它可以通过使用 psycopg2 来解决。

我写的代码如下

conn = psycopg2.connect(user='', host='', password='', database='')

query = "select * from latest_value where {column} = any(%s)"
query = query.format(**dict(column=col_name))
results = pd.read_sql_query(query, conn, params=(args,))

注意查询中的变化。in (%s)我没有使用 ,而是使用=any(%s)了 psycopg2 文档中的内容。

另请注意,要使上述内容起作用, args 需要是 Python 列表,而不是元组。


推荐阅读