将列表绑定到 Pandas read_sql_query 中的参数和其他参数
Binding list to params in Pandas read_sql_query with other params
我一直在尝试测试使我的代码达到 运行 的各种方法。首先,我有这个列表:
member_list = [111,222,333,444,555,...]
我试图将它传递到这个查询中:
query = pd.read_sql_query(
"""
select member id
,yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in ?
""", db2conn, params = [201601, 201603, member_list])
但是,我收到一条错误消息:
'Invalid parameter type. param-index=2 param-type=list', 'HY105'
所以我环顾四周并尝试使用格式化字符串:
query = pd.read_sql_query(
"""
select member id
,yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (%s)
""" % ','.join(['?']*len(member_list), db2conn, params = [201601, 201603, tuple(member_list)])
现在,我收到错误:
'The SQL contains 18622 parameter markers, but 3 parameters were supplied', 'HY000'
因为它要填写格式化字符串中的所有 ?
占位符。
所以,最终,有没有办法以某种方式评估列表并将每个单独的元素传递给绑定到 ?
,或者我可以使用另一种方法来让它工作吗?
顺便说一句,我正在使用 pyodbc
作为我的连接器。
提前致谢!
将其分为三个部分以帮助隔离问题并提高可读性:
- 构建 SQL 字符串
- 设置参数值
- 执行pandas.read_sql_query
建立SQL
首先确保 ?
占位符设置正确。使用str.format with str.join and len根据member_list
长度动态填充?
s。下面的示例假设 3 member_list
个元素。
例子
member_list = (1,2,3)
sql = """select member_id, yearmonth
from queried_table
where yearmonth between {0} and {0}
and member_id in ({1})"""
sql = sql.format('?', ','.join('?' * len(member_list)))
print(sql)
Returns
select member_id, yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (?,?,?)
设置参数值
现在确保参数值组织成一个平面元组
例子
# generator to flatten values of irregular nested sequences,
# modified from answers
def flatten(l):
for el in l:
try:
yield from flatten(el)
except TypeError:
yield el
params = tuple(flatten((201601, 201603, member_list)))
print(params)
Returns
(201601, 201603, 1, 2, 3)
执行
最后在 read_sql_query
调用中将 sql
和 params
值放在一起
query = pd.read_sql_query(sql, db2conn, params)
警告! 虽然我在这里提出的解决方案有效,但它很容易受到 SQL 注入攻击。
因此,它应该永远不会直接在后端代码中使用!
只对离线分析安全。
如果您使用的是 python 3.6+,您还可以在查询中使用格式化字符串文字 (cf https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)
start, end = 201601, 201603
selected_members = (111, 222, 333, 444, 555) # requires to be a tuple
query = f"""
SELECT member_id, yearmonth FROM queried_table
WHERE yearmonth BETWEEN {start} AND {end}
AND member_id IN {selected_members}
"""
df = pd.read_sql_query(query, db2conn)
query = 'Select count(*) cnt from TBL_DESK_AUDIT where trunc(DATETIMECREATED) = trunc(sysdate) and DESK_NAME =' + "'"+dataframe_list1[0][0] + "'"
print(query)
df_TBL_DESK_AUDIT = pd.read_sql_query(query, connect);
我一直在尝试测试使我的代码达到 运行 的各种方法。首先,我有这个列表:
member_list = [111,222,333,444,555,...]
我试图将它传递到这个查询中:
query = pd.read_sql_query(
"""
select member id
,yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in ?
""", db2conn, params = [201601, 201603, member_list])
但是,我收到一条错误消息:
'Invalid parameter type. param-index=2 param-type=list', 'HY105'
所以我环顾四周并尝试使用格式化字符串:
query = pd.read_sql_query(
"""
select member id
,yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (%s)
""" % ','.join(['?']*len(member_list), db2conn, params = [201601, 201603, tuple(member_list)])
现在,我收到错误:
'The SQL contains 18622 parameter markers, but 3 parameters were supplied', 'HY000'
因为它要填写格式化字符串中的所有 ?
占位符。
所以,最终,有没有办法以某种方式评估列表并将每个单独的元素传递给绑定到 ?
,或者我可以使用另一种方法来让它工作吗?
顺便说一句,我正在使用 pyodbc
作为我的连接器。
提前致谢!
将其分为三个部分以帮助隔离问题并提高可读性:
- 构建 SQL 字符串
- 设置参数值
- 执行pandas.read_sql_query
建立SQL
首先确保 ?
占位符设置正确。使用str.format with str.join and len根据member_list
长度动态填充?
s。下面的示例假设 3 member_list
个元素。
例子
member_list = (1,2,3)
sql = """select member_id, yearmonth
from queried_table
where yearmonth between {0} and {0}
and member_id in ({1})"""
sql = sql.format('?', ','.join('?' * len(member_list)))
print(sql)
Returns
select member_id, yearmonth
from queried_table
where yearmonth between ? and ?
and member_id in (?,?,?)
设置参数值
现在确保参数值组织成一个平面元组
例子
# generator to flatten values of irregular nested sequences,
# modified from answers
def flatten(l):
for el in l:
try:
yield from flatten(el)
except TypeError:
yield el
params = tuple(flatten((201601, 201603, member_list)))
print(params)
Returns
(201601, 201603, 1, 2, 3)
执行
最后在 read_sql_query
调用中将 sql
和 params
值放在一起
query = pd.read_sql_query(sql, db2conn, params)
警告! 虽然我在这里提出的解决方案有效,但它很容易受到 SQL 注入攻击。 因此,它应该永远不会直接在后端代码中使用! 只对离线分析安全。
如果您使用的是 python 3.6+,您还可以在查询中使用格式化字符串文字 (cf https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)
start, end = 201601, 201603
selected_members = (111, 222, 333, 444, 555) # requires to be a tuple
query = f"""
SELECT member_id, yearmonth FROM queried_table
WHERE yearmonth BETWEEN {start} AND {end}
AND member_id IN {selected_members}
"""
df = pd.read_sql_query(query, db2conn)
query = 'Select count(*) cnt from TBL_DESK_AUDIT where trunc(DATETIMECREATED) = trunc(sysdate) and DESK_NAME =' + "'"+dataframe_list1[0][0] + "'"
print(query)
df_TBL_DESK_AUDIT = pd.read_sql_query(query, connect);