在 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)"""
然后format
和execute
变为:
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 查询?