尝试将参数传递给简单的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注入并使用参数化查询的方法。
首先,如果您将panda与SQLite以外的任何数据库一起使用,那么您应该使用SQLAlchemy。当您将select()
对象传递给Panda.read_sql_query()
方法时,SQLAlchemy将自动构建所需的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
"""