2012-09-12 40 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和數據庫抽象層。我在兩個角色中都使用過這個庫(通常是同時)。一旦通過,你往往不會回去。 :-) –