python - mysql query not working

拈花ヽ惹草 提交于 2019-12-25 17:00:14

问题


I am trying to load data into a MySQL table with the following Python script:

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
)

I am getting the following error:

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

I know it is a quotes issue while passing the query, but I am having a hard time trying to figure it out. Can someone please suggest where am I making a mistake?

This is the query I want to execute:

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'

This is my table structure:

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

回答1:


It seems you need to add quotes for pipeline_name and grid

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



回答2:


If you print out the constructed MySQL statement you'll see that you don't have the required single quotes around the string values in some of your assignments.

You will need to add single quotes around each of those values and, additionally, double-up any single-quotes in the string value (that is, galaxy should become 'galaxy' but Joe's Galaxy should become 'Joe''s Galaxy').

You can use a function along these lines:

 def qstr(in_string, quote_char="'"):

     return quote_char + in_string.replace(quote_char, quote_char*2) + quote_char

and then modify your code like this: "pipeline = " + qstr(pipeline_name).




回答3:


MySQLdb will deal with the quoting issue for you if you use parameters instead of all that string concatenation. The simplest way to do this is:

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

%s is used as a placeholder for a parameter, and parameters are inserted in order; you must supply parameters for every placeholder in the query string. Alternatively, you can use named parameters with a dictionary mapping:

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

There is a limit to which parts of the statement can be replaced in this way (see the paramstyle attribute in the MySQLdb user guide):

Parameter placeholders can only be used to insert column values. They can not be used for other parts of SQL, such as table names, statements, etc.

So in your query, you can pass date, pipeline_name and grid as parameters, but not jobsummaryfile because it is a file path, not a column value. You can also use implicit string concatenation to make everything a little more readable, and simplify your statement by removing the unnecessary user variables:

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

The only reason you would need (@col1, @col2, @col3, @col4) is if you needed to manipulate all four columns of your input file before inserting them into your table. For instance, if you wanted to make sure your job name was always upper case, you could do it like this:

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';

But since all you're doing is inserting the data as-is, all those user variables just make the query longer and harder to read; leave them out.


Personally, I like to use Python's multi-line strings with my SQL statements. This lets me do two things: First, I can quickly copy/paste entire statements to and from Workbench for testing purposes; and second, I can start with a comment that will help me identify which queries are currently running when I'm checking the server administration tab. The down-side to this is that it's a little more verbose, especially when inserting things like table names.

For example:

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


来源:https://stackoverflow.com/questions/24131196/python-mysql-query-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!