【问题标题】:Pandas read_sql with parameters带参数的 Pandas read_sql
【发布时间】:2025-11-26 09:35:01
【问题描述】:

有没有关于如何在 Pandas 中通过 SQL 查询传递参数的示例?

特别是我使用 SQLAlchemy 引擎连接到 PostgreSQL 数据库。到目前为止,我发现以下工作:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN %s AND %s'),
                   db,params=[datetime(2014,6,24,16,0),datetime(2014,6,24,17,0)],
                   index_col=['Timestamp'])

Pandas 文档说 params 也可以作为 dict 传递,但我似乎无法通过尝试使其工作:

df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                     'where "Timestamp" BETWEEN :dstart AND :dfinish'),
                   db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                   index_col=['Timestamp'])

从 Pandas 运行这些类型的查询的推荐方法是什么?

【问题讨论】:

    标签: python sql pandas psycopg2


    【解决方案1】:

    read_sql 文档说这个params 参数可以是列表、元组或字典(请参阅docs)。

    要在 sql 查询中传递值,可以使用不同的语法:?:1:name%s%(name)s(请参阅PEP249)。
    但并非所有数据库驱动程序都支持所有这些可能性,支持哪种语法取决于您使用的驱动程序(我想在您的情况下为psycopg2)。

    在您的第二种情况下,当使用 dict 时,您使用的是“命名参数”,并且根据 psycopg2 文档,它们支持 %(name)s 样式(所以不支持 :name 我想),请参阅http://initd.org/psycopg/docs/usage.html#query-parameters.
    所以使用这种风格应该可以工作:

    df = psql.read_sql(('select "Timestamp","Value" from "MyTable" '
                         'where "Timestamp" BETWEEN %(dstart)s AND %(dfinish)s'),
                       db,params={"dstart":datetime(2014,6,24,16,0),"dfinish":datetime(2014,6,24,17,0)},
                       index_col=['Timestamp'])
    

    【讨论】:

    • 这很有帮助 - 我正在使用 psycopg2,所以 '%(name)s 语法完美运行。
    • 我们可能应该在文档字符串中提及一些相关内容:github.com/pydata/pandas/issues/7573
    • 此解决方案不再适用于 Postgres - 需要使用 :notation,然后确保使用 sqlalchemy.text() 包装 SQL 字符串
    • 可以通过 paramstyle 属性在几乎每个数据库驱动程序中动态查找参数样式的正确字符。这实际上是 PEP 249 定义的一部分。