在查询中使用pandas和命名参数从mysql表中读取

时间:2017-07-02 11:02:52

标签: python mysql pandas sqlalchemy

我尝试执行以下查询

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}

我尝试以下pandas代码

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

我使用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())}] 作为驱动程序和MySQL数据库。如何在sql查询中传递命名参数?

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

SPDRP_FRIENDLYNAME

3 个答案:

答案 0 :(得分:3)

根据pandas.read_sql_query documentation

  

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

     

要传递给execute方法的参数列表。用于传递参数的语法取决于数据库驱动程序。检查数据库驱动程序文档,了解支持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})

答案 1 :(得分:1)

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}
)

答案 2 :(得分:0)

如前所述,您的驱动程序无法使用冒号语法识别命名的占位符。该查询按原样传递给MySQL,然后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})