如何为 SELECT 查询的 IN 子句传递参数以检索 pandas DataFrame?

How can I pass parameters for the IN clause of a SELECT query to retrieve a pandas DataFrame?

尝试将参数传递给简单的 SELECT 查询:

query = """SELECT * from tbl_tab where name in {};"""

我通过这段代码来操作我的数据框,我的想法是能够将 1 到 n 个参数传递到我的查询中:

conn = pyodbc.connect(conx_string)
t = tuple(["N","M"])
crsr = conn.cursor()
data = crsr.execute(query.format(t))
rows = [list(x) for x in data]
columns = [column[0] for column in crsr.description]
df = pd.DataFrame(rows, columns=columns)

我得到了预期的结果。但是,当将单个参数传递给 t 时:具有 t = tuple(["N"])

我收到错误 ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near ')'. (102) (SQLExecDirectW)")

有什么想法吗?

您正在使用元组的字符串表示形式将 注入 到您的 SQL 语句中。它适用于 tuple(["N","M"]),因为你得到 … IN ('N', 'M')。但是,tuple(["N"]) 失败,因为结果是 … IN ('N',) 并且尾随逗号是无效的 SQL 语法。考虑一种避免 SQL 注入 并使用参数化查询的方法。

首先,如果您将 pandas 与 SQLite 以外的任何数据库一起使用,您应该使用 SQLAlchemy。 SQL当您将 select() 对象传递给 pandas .read_sql_query() 方法时,Alchemy 将自动构建所需的 SQL 语句:

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine(
    "mssql+pyodbc://scott:tiger^5HHH@mssql_199",
)
tbl_tab = sa.Table("tbl_tab", sa.MetaData(), autoload_with=engine)

# full contents of table:
with engine.begin() as conn:
    print(conn.execute(sa.select(tbl_tab)).fetchall())
    # [(1, 'Alicia'), (2, 'Brandon'), (3, 'Candace')]

# retrieve subset of rows into a DataFrame
name_list = ["Alicia", "Brandon"]
my_select = sa.select(tbl_tab).where(tbl_tab.c.name.in_(name_list))
df = pd.read_sql_query(my_select, engine)
print(df)
"""
   id     name
0   1   Alicia
1   2  Brandon
"""