python - mysql查询不起作用

时间:2014-06-10 00:42:50

标签: python mysql mysql-python

我正在尝试使用以下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    |                |  

3 个答案:

答案 0 :(得分:1)

您似乎需要为pipeline_namegrid

添加引号
 cursor.execute(" ... pipeline='"+pipeline_name+"', grid='"+grid+"'")

答案 1 :(得分:0)

如果您打印出构造的MySQL语句,您将看到在某些作业中,字符串值周围没有所需的单引号。

您需要在每个值周围添加单引号,并且另外,将字符串值中的任何单引号加倍(即galaxy应变为'galaxy'但{{1}应该成为Joe's Galaxy)。

你可以沿着这些方向使用一个函数:

'Joe''s Galaxy'

然后修改您的代码: def qstr(in_string, quote_char="'"): return quote_char + in_string.replace(quote_char, quote_char*2) + quote_char

答案 2 :(得分:0)

如果您使用参数而不是所有字符串连接,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))