使用'?'查询sqlite3和python

时间:2014-10-26 11:50:17

标签: python database sqlite

我有一个包含三列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')...]。我该怎么办 ?请给我一些想法。

1 个答案:

答案 0 :(得分:3)

您不能将占位符用于标识符 - 仅用于文字值。

我不知道在这种情况下建议什么,因为你的函数需要一个数据库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 injectiontainted data的问题已有详细记录,但此处是摘要。

原则是,理论上,只要所有数据源都在他的控制之下,程序员就可以编写安全可靠的程序。一旦他们使用来自程序外部的任何信息而不检查其完整性,安全性就会受到威胁。

此类信息的范围从显而易见的 - 在命令行上传递的参数 - 到模糊 - 如果PATH环境变量是可修改的,那么有人可以诱导程序执行完全不同的文件打算一个。

Perl提供直接帮助以避免Taint Checking出现此类情况,但 SQL注入是与此相关的门户。

假设您从未经验证的外部源获取数据库列的值,并且该值在您的程序中显示为$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's excellent XKCD comic

中得到了体现