我在Python中使用Pyodbc运行一些SQL查询。我正在使用的内容实际上比这更长,但是此示例捕获了我正在尝试执行的操作:
connection = pyodbc.connect(...)
cursor = connection.cursor(...)
dte = '2018-10-24'
#note the placeholders '{}'
query = """select invoice_id
into #output
from table1 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{}'
insert into #output
select invoice_id
from table2 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{}'"""
#this is where I need help as explained below
cursor.execute(query.format(dte, dte))
output = pd.read_sql("""select *
from #output"""
, connection)
在上面,由于只有两个'{}'
,因此我将dte
传递给query.format()
两次。但是,在我使用的更复杂的版本中,我有19个'{}'
,因此我想这意味着我需要将'dte'
传递给'query.format{}'
19次。我尝试将其作为列表传递,但是没有用。将变量传递给函数时,是否真的需要写出19次变量?
答案 0 :(得分:2)
请考虑使用UNION ALL
查询来避免临时表的需要,并考虑使用parameterization来设置qmark占位符,并在后续步骤中将值绑定到它们。并使用相同的值将参数列表/元组乘以所需的数字:
dte = '2018-10-24'
# NOTE THE QMARK PLACEHOLDERS
query = """select invoice_id
from table1 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = ?
union all
select invoice_id
from table2 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = ?"""
output = pd.read_sql(query, connection, params=(dte,)*2)
答案 1 :(得分:1)
我同意这些评论,pandas.read_sql有一个params参数,可以防止sql注入。
请参见this post了解如何根据数据库使用它。
Pyodbc在execute方法上具有相同的参数。
# standard cursor.execute("select a from tbl where b=? and c=?", (x, y)) # pyodbc extension cursor.execute("select a from tbl where b=? and c=?", x, y)
要回答最初的问题,即使对构建SQL查询来说是不好的做法:
在将变量传递给函数时,是否真的需要写出19次变量?
您当然不会:
query = """select invoice_id
into #output
from table1 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{dte}'
insert into #output
select invoice_id
from table2 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{dte}'""".format(**{'dte': dte})
或:
query = """select invoice_id
into #output
from table1 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{0}'
insert into #output
select invoice_id
from table2 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{0}'""".format(dte)
query = f"""select invoice_id
into #output
from table1 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{dte}'
insert into #output
select invoice_id
from table2 with (nolock)
where system_id = 'PrimaryColor'
and posting_date = '{dte}'"""
请注意在“”“ ...”“”之前的f的用法