在 Python 的 SQL DBI 中参数化带引号的字符串

Posted

技术标签:

【中文标题】在 Python 的 SQL DBI 中参数化带引号的字符串【英文标题】:Parameterize a quoted string in Python's SQL DBI 【发布时间】:2015-03-25 10:44:10 【问题描述】:

我正在使用pg8000 通过 Python 连接到 PostgreSQL 数据库。我希望能够通过cursor.execute 方法将日期作为参数发送:

def info_by_month(cursor, year, month):
    query = """
    SELECT *
    FROM info
    WHERE date_trunc('month', info.created_at) =
          date_trunc('month', '%s-%s-01')
    """
    cursor.execute(query, (year, month))
    return cursor

这将引发错误:InterfaceError: '%s' not supported in a quoted string within the query string。可以使用 Python 的字符串格式在其中插入日期。使用字符串格式化迷你语言提供了一种数据验证措施来防止 SQL 注入攻击,但它仍然很丑。

def info_by_month(cursor, year, month):
    query = """
    SELECT *
    FROM info
    WHERE date_trunc('month', info.created_at) =
          date_trunc('month', ':04-:02-01')
    """.format(year, month)
    cursor.execute(query)
    return cursor

如何将带引号的字符串发送到cursor.execute 方法?

【问题讨论】:

【参考方案1】:

提前执行format,然后将生成的字符串传递给execute。这样可以避免 SQL 注入 的可能性,但仍然可以获得所需的格式。

例如查询变为:

query = """
    SELECT *
    FROM info
    WHERE date_trunc('month', info.created_at) =
          date_trunc('month', %s)"""

然后formatexecute 变为:

dateStr = ":04-:02-01".format(year, month)
cursor.execute(query, dateStr)

我使用 psycopg2,但似乎 pg8000 遵循相同的 DBI 标准,所以我希望这适用于 pg8000 也是。

【讨论】:

仅供参考,这就是我在第二个代码 sn-p 中提到的内容。我想知道是否有可能进一步改进。 我的代码实际上与您的第二个 sn-p 不同。在您的第二个 sn-p 中,您正在执行 format,然后将整个字符串传递给 execute。这意味着您没有让 SQL 库进行任何插值。在我的示例中,我正在执行format,然后将其作为参数传递给execute,然后SQL 库可以根据需要进行插值,避免潜在的SQL 注入。基本上,我的代码 sn-p 是您的问题的答案“如何将带引号的字符串发送到 cursor.execute 方法?” 标记为正确,因为它比我能想到的任何东西都更明智! 谢谢。很高兴为您提供帮助。【参考方案2】:

有可能通过串联来实现,这会损害可读性。

query = """
  SELECT *
  FROM info
  WHERE date_trunc('month', info.created_at) =
        date_trunc('month', %s || '-' || %s || '-01')
"""
cursor.execute(query, (year, month))

【讨论】:

我认为我的代码风格更具可读性,但我想这可能是个人喜好...... 同意。添加它只是为了记录的完整性。再次感谢您抽出宝贵时间回答。

以上是关于在 Python 的 SQL DBI 中参数化带引号的字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何打印 Perl 的 DBI 填充占位符后执行的 SQL 查询?

P2219 [HAOI2007]修筑绿化带

[HAOI2007] 修筑绿化带

如何使用 Perl DBI 检索 DB2 SQL 存储过程的返回值?

使用R(DBI包)从SQL Server表中删除行

Perl DBI - 使用多个语句运行 SQL 脚本