2016-02-11 47 views
1

我在sqlite3數據庫中有一個寬表,我希望動態查詢Python腳本中的某些列。我知道it's bad to inject parameters by string concatenation,所以我嘗試使用參數替代。在Python sqlite3中替換列名查詢

我發現,當我使用參數替換來提供列名時,我得到了意想不到的結果。小例子:

import sqlite3 as lite 

db = lite.connect("mre.sqlite") 
c = db.cursor() 

# Insert some dummy rows 
c.execute("CREATE TABLE trouble (value real)") 
c.execute("INSERT INTO trouble (value) VALUES (2)") 
c.execute("INSERT INTO trouble (value) VALUES (4)") 
db.commit() 


for row in c.execute("SELECT AVG(value) FROM trouble"): 
    print row # Returns 3 

for row in c.execute("SELECT AVG(:name) FROM trouble", {"name" : "value"}): 
    print row # Returns 0 

db.close() 

有沒有更好的方式來做到這一點不是簡單地注入列名成字符串並運行它?

+0

同意,這就是答案! –

+1

更好:http://stackoverflow.com/questions/6514274/how-do-you-escape-strings-for-sqlite-table-column-names-in-python –

回答

0

正如Rob剛纔在他的評論中指出的那樣,有一個相關的SO帖子包含了我的答案。這些替代結構被稱爲「佔位符」,這就是爲什麼我最初沒有找到答案。沒有列名的佔位符模式,因爲dynamically specifying columns is not a code safety issue

它歸結爲「安全」的含義。傳統的看法是, 使用正常的python字符串操作將值放入您的 查詢中並不「安全」。這是因爲如果你這樣做的話,有各種各樣的東西 可能會出錯,而這些數據通常來自用戶的 ,並且不受你控制。您需要100%可靠的方式 正確轉義這些值,以便用戶無法將SQL注入 數據值並讓數據庫執行它。所以圖書館作家 這個工作;你永遠不應該。

但是,如果您正在編寫通用的幫助程序代碼以便在數據庫中操作 ,那麼這些注意事項並不適用。你是 隱含給任何人可以調用這樣的代碼訪問數據庫中的所有內容 ;這就是幫手代碼的要點。因此,現在安全問題是確保用戶生成的數據永遠不會在此類代碼中使用 。這是編碼中的一個普遍安全問題,並且與盲目地放棄用戶輸入字符串一樣是個問題。這是將值插入到查詢中的一個不同的問題,因爲您希望能夠安全地處理用戶輸入數據,因此您需要 。

所以,解決的辦法是,有擺在首位沒有問題:使用注射字符串格式化的值,快樂,與你的生活。

0

爲什麼不使用字符串格式?

for row in c.execute("SELECT AVG({name}) FROM trouble".format(**{"name" : "value"})): 
    print row # => (3.0,) 
+0

謝謝!這實際上是通過將字段名稱注入字符串的意思;對不起,如果不明確。 –