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

Parameterize a quoted string in Python's SQL DBI

我正在使用 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 方法?

提前做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

可以通过连接来实现这一点,但这会损害可读性。

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