我希望之前没有人问过这个问题,我不确定使用什么关键字。
假设我想写一个函数,可以接受小于或等于语句的查询…
import MySQLdb
def query1(date,le):
'''
query1('2013-01',<= )
>>> 10
'''
query = '''
select *
from table
where number {x} 1
and date = {dt}
'''.format(dt=date,x=le)
cursor.execute(query)
rslt = cursor.fetchall()
return rslt
那么最好的方法是什么呢?
您可以将比较操作符作为字符串传递给函数:
query1('2013-01', '<=')
这将把用于操作符in的字符串插入到查询中,结果为
select *
from table
where number <= 1
and date = 2013-01
请注意,通过插入字符串直接构建SQL查询是SQL注入的潜在向量。如果允许用户提供他们自己的日期字符串,用户可能会在其中注入一些SQL代码并运行恶意代码。查看查询参数化以获取更多信息。
如果你想防止SQL注入,你应该做如下的事情。允许的操作符列表被仔细地列入白名单,因此只能使用有效和安全的操作符。这用于构建查询。然后通过cursor.execute()
命令将日期注入到查询中。然后MySQLdb
处理从您的数据构造一个安全查询,并且不允许恶意用户在日期字符串中注入他们自己的SQL。
import MySQLdb
def query1(date, comp):
query = '''
select *
from table
where number {comp} 1
and date = %s
'''.format(comp=sql_comp_operator(comp))
cursor.execute(query, (date, ))
return cursor.fetchall()
def sql_comp_operator(comp):
operators = {
'lt': '<',
'lte': '<',
'gt': '>',
'gte': '>=',
}
if comp in operators:
return operators[comp]
else:
raise ValueError("Unknown comparison operator '{}'".format(comp))
query1('2013-01', 'lte')
理想情况下,您希望使用ORM来防止SQL注入攻击(我更喜欢SQLAlchemy/Elixir),这将允许您执行以下操作:
q = session.query(User).
filter(User.id <= 1).
filter(User.date_of_birth == date)
听起来像你想要"le"是一个函数/lambda,你可以传递进去,但我不知道有任何方法将该lambda转换为一个字符串,用于放入你的查询。例如,您可以这样调用它:
query1('2013-01-01', lambda x,y: x <= y)
但是没有真正的方法,我知道在你的查询转换为"<="。但是,如果您将其作为字符串传入,则可以通过传入具有与这些块相同名称的键的字典来使用命名块的格式,例如:
sql = """
select *
from table
where number {operation} 1
and date = '{date}'
"""
data = {
"operation": "<=",
"date": "2013-01-01"
}
query = sql.format(**data)