【问题标题】:Reading from mysql tables using pandas and named parameters in query在查询中使用 pandas 和命名参数从 mysql 表中读取
【发布时间】:2017-07-02 11:02:52
【问题描述】:

我尝试执行以下查询

SELECT user_id, user_agent_id, requests 
FROM riskanalysis_user_http_ua_stats
WHERE since>= :since AND until< :until'

我尝试以下熊猫代码

sql = 'SELECT user_id, user_agent_id, requests ' \
      'FROM riskanalysis_user_http_ua_stats ' \
      'WHERE since>= :since AND until< :until'

dataframe_records = pd.read_sql_query(sql, engine,
                                      params={'since':datetime_object,
                                              'until':datetime_object}

我收到以下错误

sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string 'SELECT user_id, user_agent_id, requests FROM riskanalysis_user_http_ua_stats WHERE since>= :since AND until< :until'

我使用pymysql 作为驱动程序和 MySQL 数据库。如何在 sql 查询中传递命名参数?

编辑 1:更正了参数顺序,但现在我得到以下内容

sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) (1064, u"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':since AND until< :until' at line 1") [SQL: 'SELECT user_id, user_agent_id, requests FROM riskanalysis_user_http_ua_stats WHERE since>= :since AND until< :until'] [parameters: {'since': datetime.datetime(2015, 6, 18, 0, 0, tzinfo=tzutc()), 'until': datetime.datetime(2015, 6, 18, 0, 2, tzinfo=tzutc())}]

【问题讨论】:

    标签: python mysql pandas sqlalchemy


    【解决方案1】:

    根据pandas.read_sql_query documentation

    params : list, tuple or dict, optional, default: None

    传递给执行方法的参数列表。用于传递参数的语法取决于数据库驱动程序。检查您的数据库驱动程序文档,了解 PEP 249 的 paramstyle 中描述的五种语法样式中的哪一种受支持。例如。对于 psycopg2,使用 %(name)s 所以使用 params={‘name’ : ‘value’}

    如果您随后查看PEP 249's paramstyle,您会看到许多选项。但是PyMySQL's execute documentation 声明

    如果 args 是列表或元组,则 %s 可以用作查询中的占位符。

    如果 args 是 dict,则 %(name)s 可以用作查询中的占位符。

    所以,适用于你的情况,那就是:

    sql = 'SELECT user_id, user_agent_id, requests ' \
          'FROM riskanalysis_user_http_ua_stats ' \
          'WHERE since>= %s AND until< %s'
    
    dataframe_records = pd.read_sql_query(sql, engine,
                                          params=(datetime_object, datetime_object))
    

    sql = 'SELECT user_id, user_agent_id, requests ' \
          'FROM riskanalysis_user_http_ua_stats ' \
          'WHERE since>= %(since)s AND until< %(until)s'
    
    dataframe_records = pd.read_sql_query(sql, engine,
                                          params={'since':datetime_object,
                                                  'until':datetime_object})
    

    【讨论】:

    • 一个小小的初学者笔记,一开始就难倒我。如果您只有一个参数,并且正在使用带有(datetime_object, datetime_object) 的方法,那么您需要一个尾随逗号,即(mySingleValue,)
    【解决方案2】:

    pandas.read_sql_query 期望在引擎之前查询 sql,并尝试将您的查询解析为数据库 URI。
    https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_sql_query.html

    dataframe_records = pd.read_sql_query(sql, engine,
          params={'since':datetime_object,'until':datetime_object}
    )
    

    【讨论】:

      【解决方案3】:

      正如所指出的,您的驱动程序无法识别使用冒号语法的命名占位符。查询按原样传递给 MySQL,然后它会抱怨占位符,因为它们是语法错误。一个解决方案是使用 SQLAlchemy text() 构造,它将命名占位符转换为驱动程序可以理解的格式:

      from sqlalchemy import text
      
      sql = text(sql)
      dataframe_records = pd.read_sql_query(sql, engine,
                                            params={'since':datetime_object,
                                                    'until':datetime_object})
      

      【讨论】:

        猜你喜欢
        • 2017-07-26
        • 1970-01-01
        • 2020-08-23
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-18
        • 1970-01-01
        相关资源
        最近更新 更多