0

我有一个单一的任务,我正在实现一个用户通过网页与之交互的数据库。目标是根据某些条件搜索书籍。这是一个更大项目中的一个模块。

我想让用户能够选择他们想要的标准和顺序,但以下似乎不起作用:

cursor.execute("SELECT * FROM Books WHERE ? REGEXP ? ORDER BY ? ?", [category, criteria, order, asc_desc])

我不知道为什么,因为当我走的时候

cursor.execute("SELECT * FROM Books WHERE title REGEXP ? ORDER BY price ASC", [criteria])

我得到了完整的结果。有没有办法在不诉诸注入的情况下解决这个问题?

数据组织在一个表中,其中图书的 ISBN 是主键,每行有很多列,例如书名、作者、出版商等。应该允许用户选择这些列中的任何一个并执行搜索.

4

1 回答 1

1

通常,SQL 引擎只支持values参数,而不支持表名、列名等参数。 sqlite 本身和 Python 的 sqlite 模块都是如此。

这背后的原因部分是历史原因(传统笨拙的数据库 API 有显式bind调用,您必须说明您绑定了哪个列号与哪个类型的哪个值等),但主要是因为没有太多充分的理由来参数化值.

一方面,您无需担心表名和列名的引用或类型转换。另一方面,一旦您开始让最终用户来源的文本指定一个表或列,就很难看出它们还会造成什么其他危害。

此外,从性能的角度来看(如果您阅读sqlite 文档- 参见第 3.0 节 - 您会注意到他们将参数绑定视为性能问题,而不是安全问题),数据库引擎可以重用准备好的优化查询在给定不同的值时计划,但在给定不同的列时不计划。


那么,你能做些什么呢?

好吧,动态生成 SQL 字符串是一种选择,但不是唯一一种。

首先,这种事情通常是数据模型损坏的标志,需要进一步规范化。也许你应该有一个BookMetadata表,其中有很多行——每行都有一个字段名和一个值——对于每个Book

其次,如果您想要就这段代码而言在概念上被规范化,但实际上是非规范化的(为了提高效率,或者因为对于其他一些代码不应该被规范化)......函数非常适合。create_function包装器,您可以在使用时将参数传递给该函数execute

于 2013-11-06T00:15:53.830 回答