我正在尝试使用以下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 | |
答案 0 :(得分:1)
您似乎需要为pipeline_name
和grid
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的其他部分,例如表名,语句等。
因此,在您的查询中,您可以将date
,pipeline_name
和grid
作为参数传递,但不能传递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))