【问题标题】:An elegant way to pass repeating argument to sqlite query [duplicate]将重复参数传递给 sqlite 查询的一种优雅方式[重复]
【发布时间】:2019-01-13 05:32:37
【问题描述】:

从我的Python 代码(实际上是Flask 应用程序),我需要执行sqlite 查询,结构如下

SELECT some_column FROM My_table WHERE some_column=some_value;

现在,some_column 在查询中重复出现两次,执行它的一种方法是:

cursor.execute('SELECT ? FROM Users WHERE ?=?;', (some_column, some_column, some_value))

这不是很好/Pythonic。然后我想出了:

cursor.execute('SELECT {0} FROM Users WHERE {0}=?;'.format(some_column), (some_value,))

最后,我一直使用.format()

cursor.execute('SELECT {0} FROM Users WHERE {0}={1};'.format(some_column, some_value), ())

我想知道是否有更漂亮和/或更 Pythonic 的方式将重复参数传递到 sqlite 的cursor.execute()

【问题讨论】:

  • 如果您在 SQL 查询中使用format(),您将容易受到 SQL 注入攻击。

标签: python sqlite


【解决方案1】:

这不是一个很大的改进,但是由于您标记了 Python 3,请考虑f-string

f"SELECT {col} FROM Users WHERE {col}={val}"

正如 Klaus D. 在评论中指出的那样,允许值是格式字符串并不是最佳实践,因为在某些情况下,这会使您的代码容易受到 SQL 注入的攻击。

它不那么紧凑,但您可以使用 f-string 的 a mix(用于列名)和 sqlite ? 语法来输入值(基本上是前两个示例的混搭):

params = (val,)
q = f"SELECT {col} FROM Users WHERE {col} = ?"
cursor.execute(q, params)

【讨论】:

  • 感谢您的回答。我是否可以得出结论,使用任何形式的格式字符串是 SQL 注入不安全 用于列值,而不是列或表名?
【解决方案2】:

第一个语法不正确。在 SQL 中,参数化查询可以使用参数作为值,而不是表名或列名。

第三种形式不好,因为它硬编码查询中的值,这是最佳实践所禁止的。它曾经很常见,并且是 SQL 注入安全问题的原因。

所以唯一的可能是第二种形式:对表名和列名使用字符串构造,对值使用参数。

但无论如何,您的查询几乎是无意义的:当您修复该列值时,您会询问该列的值。对于每个选定的行,值将是 some_value

因此,我假设这是一个更复杂问题的简化示例,但如果没有更多上下文,我根本无法想象您为什么要问这个问题以及您的真正问题是什么。

【讨论】:

  • 感谢您的解释并指出不正确的语法。查询按原样发布,旨在检查数据库中是否已存在某些条目(需要唯一),例如用户注册期间的电子邮件或登录。例如。 SELECT login FROM Users WHERE login='new_login'; 如果存在则返回 new_login,否则返回 None
猜你喜欢
  • 2013-10-16
  • 2014-09-17
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
  • 2012-01-28
  • 1970-01-01
相关资源
最近更新 更多