0

我希望以前没有问过这个问题,我不确定要使用什么关键字。

假设我想编写一个可以采用小于或等于语句进行查询的函数......

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

那么最好的方法是什么?

4

2 回答 2

1

您可以将比较运算符作为字符串传递给您的函数:

query1('2013-01', '<=')

这会将运算符的字符串插入到查询中,从而导致

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')
于 2013-04-15T02:11:25.043 回答
0

理想情况下,您希望使用 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)

但是我不知道将您的查询中的它转换为“<=”的真正方法。但是,如果您将其作为字符串传入,则可以将 format 与命名块一起使用,方法是传入具有与这些块相同名称的键的字典,如下所示:

sql = """
select * 
  from   table 
  where  number {operation} 1
         and date = '{date}'
"""

data = {
    "operation": "<=",
    "date": "2013-01-01"
}

query = sql.format(**data)
于 2013-04-15T02:20:31.743 回答