【问题标题】:Python and Prepared SQL Statements using VariablesPython 和使用变量的准备好的 SQL 语句
【发布时间】:2020-10-11 09:51:29
【问题描述】:

我对 Python 还很陌生,但我正在从事一个项目,所以请原谅我的任何天生。 我正在 Python 2.7 中编写一些 SQL 语句(库尚未升级到 3),但我陷入了它们的最佳实践过程。我们正在使用 Sybase。最初我使用的是

query = "UPDATE DB..TABLE SET version = '{}' WHERE name = '{}'".format(app.version, app.name)
cursor.execute(query)

但在进一步阅读后意识到它可以注入。所以我接着看做以下事情:

query = "UPDATE DB..TABLE SET version = '%s' WHERE name = '%s'" % (app.version, app.name)
cursor.execute(query)

但让我想到这不是一回事吗?

参数也是 argparse 设置的变量,这意味着我必须在 %s 周围使用 '' 否则会引发无效列名错误。这让我很沮丧,因为如果在其他查询中未设置任何其他标志,我还希望能够默认传递 NULL(Python 中为 None),否则它显然会将“NULL”作为字符串插入。

对于这个特定的示例,2 个变量是从 ConfigParser 读取的文件中设置的,但我认为 argparse 变量仍然相同。例如

[SECTION]
application=name
version=1.0

我不太确定如何最好地解决这个问题,是的,我知道“PYTHON 3 可以更好地升级到它”,正如我在一开始所说的那样,这些库正在移植过程中。

如果您需要任何其他信息,请提出建议,我会尽我所能。

更新*** 使用我在一些 sybase 文档中找到的以下 Param 样式字符串,它可以工作,但它不会为 NULL 传递 None 并引发错误,开始认为这是 python 中 sybase 模块的限制。

cursor.execute("SELECT * FROM DB..table where app_name=@app_name", {"@app_name": app_name})
or
params = {"@appname": app.name. "@appver": app.version}
sql = "INSERT INTO DB..table (app_name, app_version) VALUES (@appname, @appversion)
cursor.execute(sql, params)

如果你有一个全局参数列表并将其提供给一个查询,如果有的话是 None 那么它会给你很多关于是 None 的错误,即使这些特定的参数没有使用查询。认为我可能会在此处为各种选项执行 IF 语句,以便多次插入以绕过此 None NULL 问题。

【问题讨论】:

  • 我可能已经找到了一部分,但不确定这是否更安全??? cursor.execute("SELECT * FROM DB..table where app_name=@app_name", {"@app_name": app_name})
  • 到了一半,需要对 NULL 插入等进行更多测试,但我会在测试后将其标记为已回答。
  • 如果您的值默认设置为 None 但参数设置为不喜欢它 Exception Sybase.DatabaseError: DatabaseError('Layer: 1, Origin: 1\nct_cmd_drop(): user api 层:外部错误:只有在命令结构空闲时才能调用此例程。',) in 忽略
  • 好的,Sybase 参数有一个奇怪的问题,它们有长度限制,因此将它们重命名为更短的名称可以在插入时使用!但现在唯一的问题是它无法识别 Python 的 None。它应该自动转换为 NULL 但它只是抛出错误而不是

标签: python sql python-2.7 sybase q


【解决方案1】:

好的,我现在已经解决了这个问题。 我必须更新 sybase 模块才能使其与 None > NULL 一起工作。

如更新问题中所述。以下是我运行查询的方式。

cursor.execute("SELECT * FROM DB..table where app_name=@app_name", {"@app_name": app_name})
or
params = {"@appname": app.name. "@appver": app.version}
sql = "INSERT INTO DB..table (app_name, app_version) VALUES (@appname, @appversion)
cursor.execute(sql, params)

【讨论】:

    【解决方案2】:

    但让我想到这不是一回事吗?

    是的,它们实际上是相同的。它们都容易受到注入攻击。

    相反,这样做:

    query = "UPDATE DB..TABLE SET version = %s WHERE name = %s"
    cursor.execute(query, [app.version, app.name])
    

    【讨论】:

    • 谢谢约翰,但我将如何解决必须在 '%s' 周围加上单引号以使其正确阅读的问题?还有NULL问题?
    • 按照你的方式尝试时,我也收到以下错误'%' 附近的语法不正确。
    • 嗯。看起来 Sybase 可能会使用问号作为占位符标记。尝试将查询字符串中的%s 替换为?
    • 同样的事情 '?' 附近的语法不正确虽然在上面的例子中我给出的 %s 确实有效,但显然它是有缺陷的
    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    相关资源
    最近更新 更多