2012-09-12 90 views
0

我目前正在建立SQL查询取决于来自用户的输入。如何做到这一点的例子可以看这里:转义动态sqlite查询?

def generate_conditions(table_name,nameValues): 
    sql = u"" 
    for field in nameValues: 
     sql += u" AND {0}.{1}='{2}'".format(table_name,field,nameValues[field]) 
    return sql 

search_query = u"SELECT * FROM Enheter e LEFT OUTER JOIN Handelser h ON e.Id == h.Enhet WHERE 1=1" 

if "Enhet" in args: 
    search_query += generate_conditions("e",args["Enhet"]) 
c.execute(search_query) 

由于SQL的每一次变化,我不能插在执行调用,这意味着我应该手动逃脱字符串值。但是,当我搜索每个点执行...

我也不是很满意我如何生成查询,所以如果有人有任何想法,另一种方式,这将是伟大的!

+0

是预先知道的表和列名? –

回答

2

你有两个选择:

  1. 切换到使用SQLAlchemy;它会使生成动态SQL更加pythonic 确保正确的引用。

  2. 由于您不能使用表名和列名的参数,因此您仍然必须使用字符串格式将这些参数包含在查询中。另一方面,您的应始终使用SQL参数,如果只有这样数据库才可以编写语句。

    从用户输入直接插入表和列名是不可取的,它是太容易以这种方式注入任意SQL语句。请根据您接受的此类名称的列表验证表名和列名。

    因此,要建立在你的榜样,我会往这个方向:

    tables = { 
        'e': ('unit1', 'unit2', ...), # tablename: tuple of column names 
    } 
    
    def generate_conditions(table_name, nameValues): 
        if table_name not in tables: 
         raise ValueError('No such table %r' % table_name) 
        sql = u"" 
        params = [] 
        for field in nameValues: 
         if field not in tables[table_name]: 
          raise ValueError('No such column %r' % field) 
         sql += u" AND {0}.{1}=?".format(table_name, field) 
         params.append(nameValues[field]) 
        return sql, params 
    
    search_query = u"SELECT * FROM Enheter e LEFT OUTER JOIN Handelser h ON e.Id == h.Enhet WHERE 1=1" 
    
    search_params = [] 
    if "Enhet" in args: 
        sql, params = generate_conditions("e",args["Enhet"]) 
        search_query += sql 
        search_params.extend(params) 
    c.execute(search_query, search_params) 
    
+0

感谢您的回应,我将深入研究SQLAlchemy,但是因为这实际上是我需要构建这样的动态查询的唯一时间,所以如果SQlAlchemy看起来过于矫枉过正,我可能会选择第二个选项。 – monoceres

+1

@monoceres:除了动态SQL生成外,SQLAlchemy还提供了一个ORM和数据库抽象层。我在两个角色中都使用过这个库(通常是同时)。一旦通过,你往往不会回去。 :-) –