【问题标题】:python - mysql query not workingpython - mysql查询不起作用
【发布时间】:2014-06-10 00:42:49
【问题描述】:

我正在尝试使用以下 Python 脚本将数据加载到 MySQL 表中:

conn = connect_db()
cursor = conn.cursor()
cursor.execute(
    "LOAD DATA LOCAL INFILE " + jobsummaryfile + " INTO TABLE daily_job_summary " +
    "FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4) " +
    "set jobname=@col1, queue=@col2, maphours=@col3, reducehours=@col4, date=" + date + 
    ", pipeline=" + pipeline_name + ", grid=" + grid
)

我收到以下错误:

_mysql_exceptions.OperationalError: (1054, "Unknown column 'galaxy' in 'field list'")

我知道在传递查询时这是一个引号问题,但我很难弄清楚。有人可以建议我在哪里犯错吗?

这是我要执行的查询:

LOAD DATA LOCAL INFILE 'file.tsv' 
    INTO TABLE daily_job_summary 
    FIELDS TERMINATED BY '\t'
    LINES TERMINATED BY '\n' 
    (@col1, @col2, @col3, @col4) 
    set jobname=@col1, queue=@col2, maphours=@col3, reducehours=@col4, 
        date=2014-01-05, pipeline='abcd', grid='AB'

这是我的表结构:

| id          | int(11)      | NO   | PRI | NULL    | auto_increment |  
| date        | date         | YES  |     | NULL    |                |  
| pipeline    | varchar(12)  | YES  |     | NULL    |                |  
| grid        | varchar(2)   | YES  |     | NULL    |                |  
| jobname     | varchar(255) | YES  |     | NULL    |                |  
| maphours    | int(11)      | YES  |     | NULL    |                |  
| reducehours | int(11)      | YES  |     | NULL    |                |  
| queue       | varchar(60)  | YES  |     | NULL    |                |  

【问题讨论】:

  • 您必须显示在 cursor.execute() 命令中发送的查询字符串、示例文件以及表架构。
  • 编辑了问题@IvanCachicatari
  • 你的表中的“星系”列在哪里?
  • galaxy 是管道名称...@furas
  • 看来pipeline_name需要加引号

标签: python mysql mysql-python


【解决方案1】:

看来您需要为pipeline_namegrid 添加引号

 cursor.execute(" ... pipeline='"+pipeline_name+"', grid='"+grid+"'")

【讨论】:

    【解决方案2】:

    如果您打印出构造的 MySQL 语句,您会发现在某些分配中,您的字符串值周围没有所需的单引号。

    您需要在每个值周围添加单引号,此外,将字符串值中的任何单引号加倍(即,galaxy 应变为 'galaxy',但 Joe's Galaxy 应变为 @987654324 @)。

    您可以按照以下方式使用函数:

     def qstr(in_string, quote_char="'"):
    
         return quote_char + in_string.replace(quote_char, quote_char*2) + quote_char
    

    然后像这样修改你的代码:"pipeline = " + qstr(pipeline_name)

    【讨论】:

      【解决方案3】:

      如果您使用参数而不是所有字符串连接,MySQLdb 将为您处理引用问题。最简单的方法是:

      cursor.execute("SELECT * FROM tbl WHERE col1 = %s;", ('foo',))
      

      %s用作参数的占位符,参数按顺序插入;您必须为查询字符串中的每个占位符提供参数。或者,您可以将命名参数与字典映射一起使用:

      cursor.execute("SELECT * FROM tbl WHERE col1 = %(col1)s;", {'col1': 'foo'})
      

      以这种方式替换语句的哪些部分是有限制的(请参阅 MySQLdb 用户指南中的the paramstyle attribute):

      参数占位符只能用于插入列值。它们不能用于 SQL 的其他部分,例如表名、语句等。

      所以在您的查询中,您可以传递datepipeline_namegrid 作为参数,但不能传递jobsummaryfile,因为它是文件路径,而不是列值。您还可以使用implicit string concatenation 使所有内容更具可读性,并通过删除不必要的用户变量来简化您的语句:

      query = ("LOAD DATA LOCAL INFILE " + jobsummaryfile + " INTO TABLE daily_job_summary "
               "FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' "
               "(jobname, queue, maphours, reducehours) "
               "set date=%s, pipeline=%s, grid=%s;")
      curs.execute(query, (date, pipeline_name, grid))
      

      您需要(@col1, @col2, @col3, @col4) 的唯一原因是您是否需要在将输入文件的所有四列插入表之前对其进行操作。例如,如果你想确保你的工作名称总是大写,你可以这样做:

      LOAD DATA LOCAL INFILE 'file.tsv'
          FIELDS TERMINATED BY '\t'
          LINES TERMINATED BY '\n'
          (@col1, queue, maphours, reducehours)
          SET jobname=UPPER(@col1), date='2014-01-05', pipeline='abcd', grid='AB';
      

      但是由于您所做的只是按原样插入数据,所有这些用户变量只会使查询变得更长且更难阅读;把它们排除在外。


      就我个人而言,我喜欢在我的 SQL 语句中使用 Python 的多行字符串。这让我可以做两件事:首先,我可以快速将整个语句复制/粘贴到 Workbench 中或从 Workbench 中复制出来以进行测试;其次,我可以从一个注释开始,它可以帮助我在检查服务器管理选项卡时识别当前正在运行的查询。这样做的缺点是它有点冗长,尤其是在插入表名之类的东西时。

      例如:

      load_from_file = """--load from {file}
      LOAD DATA LOCAL INFILE {file}
          INTO TABLE daily_job_summary
          FIELDS TERMINATED BY '\t' 
          LINES TERMINATED BY '\n'
          (jobname, queue, maphours, reducehours)
          SET date=%s, pipeline=%s, grid=%s;
      """
      curs.execute(query=load_from_file.format(file=jobsummaryfile), 
                   args=(date, pipeline_name, grid))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-10
        相关资源
        最近更新 更多