多次传递此变量的有效方法

时间:2018-10-24 17:45:42

标签: python sql-server pyodbc

我在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次变量?

2 个答案:

答案 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)

Python 3.6+

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的用法