[英]query of sqlite3 with python using '?'
我有一個包含三列id,word,essay
。我想使用( ?
)進行查詢。 sql語句為sql1 = "select id,? from training_data"
。 我的代碼如下:
def dbConnect(db_name,sql,flag):
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
if (flag == "danci"):
itm = 'word'
elif flag == "wenzhang":
itm = 'essay'
n = cursor.execute(sql,(itm,))
res1 = cursor.fetchall()
return res1
但是,當我print dbConnect("data.db",sql1,"danci")
,獲得的結果是[(1,'word'),(2,'word'),(3,'word')...].
我真正想要得到的是[(1,'the content of word column'),(2,'the content of word column')...]
。 我該怎么辦 ? 請給我一些想法。
您不能將占位符用於標識符-只能用於文字值。
我不知道在這種情況下的建議,因為您的函數需要一個數據庫nasme,一個SQL字符串和一個標記來說明如何修改該字符串。 我認為最好只通過前兩個,寫類似
sql = {
"danci": "SELECT id, word FROM training_data",
"wenzhang": "SELECT id, essay FROM training_data",
}
然后用以下任一方法調用它
dbConnect("data.db", sql['danci'])
要么
dbConnect("data.db", sql['wenzhang'])
但是,很大程度上取決於您為何要dbConnect
根據從外部傳入的字符串來決定要提取的列。 這是一個不尋常的設計。
更新-SQL注入
有關SQL注入和污染 數據的問題已得到充分證明,但這是一個摘要。
原理是,從理論上講,只要所有數據源都在他的控制之下,程序員就可以編寫安全的程序。 一旦他們在不檢查程序完整性的情況下使用程序外部的任何信息,安全性就會受到威脅。
這些信息的范圍很廣,從顯而易見的命令行參數傳遞到模糊的環境變量(如果PATH
環境變量是可修改的),那么有人可能會誘使程序執行與目標文件完全不同的文件。
Perl通過Taint Checking提供了直接的幫助來避免這種情況,但是SQL Injection是與之相關的門戶。
假設您從未經驗證的外部來源獲取數據庫列的值,並且該值在您的程序中顯示為$val
。 然后,如果你寫
my $sql = "INSERT INTO logs (date) VALUES ('$val')";
$dbh->do($sql);
那么看起來就可以了。 例如,如果$val
設置為2014-10-27
則$sql
變為
INSERT INTO logs (date) VALUES ('2014-10-27')
一切都很好。 但是,現在假設我們的數據是由不小心或徹頭徹尾的惡意軟件提供的,並且您的$val
來自其他地方,
2014-10-27'); DROP TABLE logs; SELECT COUNT(*) FROM security WHERE name != '
現在看起來不太好。 $sql
設置為此(添加了換行符)
INSERT INTO logs (date) VALUES ('2014-10-27');
DROP TABLE logs;
SELECT COUNT(*) FROM security WHERE name != '')
它像以前一樣在logs
表中添加一個條目,結束然后繼續操作,刪除整個logs
表並計算security
表中的記錄數。 那根本不是我們要記住的,我們必須謹防。
立即的解決方案是使用占位符 ?
在准備好的語句中,然后在調用execute
傳遞實際值。 這不僅可以加快處理速度,因為SQL語句僅可以准備(編譯)一次,而且可以通過為數據類型適當地引用每個提供的值並轉義任何嵌入式引號來保護數據庫免受惡意數據的侵害 ,從而無法關閉一個聲明,另一個打開另一個。
整個概念在Randall Munroe出色的XKCD漫畫中得到了幽默
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.