In python, How to update variable dynamically?

Question:

I have some data that I want to change(unixtime -> human date time).
After then, How can I update result on mysql dynamically.

>>> print data
((1424794931452.0,), (1424794931645.0,), (1424794931821.0,), (1424794932014.0,), (1424794932189.0,)



for i in data:
    dt = datetime.fromtimestamp(i[0] // 1000)
    s = dt.strftime('%Y-%m-%d %H:%M:%S')
    sql2 = "UPDATE accelerometer SET test = "+ s +"WHERE _id="+i
    cursor.execute(sql2)
    data = cursor.fetchall()
    print (s)

this is error message.

TypeError: cannot concatenate 'str' and 'tuple' objects

I want to update those below result data on Mysql dynamically. But have some problem. What is the problem?

2015-02-24 11:22:11
2015-02-24 11:22:11
2015-02-24 11:22:11
2015-02-24 11:22:12
2015-02-24 11:22:12
Asked By: Jueun Kim

||

Answers:

Your core problem is that you’re trying to put together a self-sufficient string (with string concatenation in your case, problems with string interpolation are more common, but it’s pretty much the same issue).

Rather, use placeholders:

sql2 = "UPDATE accelerometer SET test = %s WHERE _id= %s"

then pass the data to execute:

cursor.execute(sql2, (s, i))

which will do the right thing for you.

It is, of course, possible, though tricky, to build the right stand-alone string — but it’s still very wrong to do so, see https://xkcd.com/327/ and don’t expose yourself, ever!, to SQL-injection risks: use placeholders and data in execute, instead!

Answered By: Alex Martelli

You are looping over tuples with an id, not a list of ids:

((1424794931452.0,), (1424794931645.0,), (1424794931821.0,), (1424794932014.0,), (1424794932189.0,)

So each i is set to one of those tuples. Extract the id, by using indexing or by adding a comma to the for loop assignment:

for i in data:
    dt = datetime.fromtimestamp(i[0] // 1000)
    s = dt.strftime('%Y-%m-%d %H:%M:%S')
    sql2 = "UPDATE accelerometer SET test = " + s + "WHERE _id=" + i[0]
    cursor.execute(sql2)

or

for i, in data:
    dt = datetime.fromtimestamp(i // 1000)
    s = dt.strftime('%Y-%m-%d %H:%M:%S')
    sql2 = "UPDATE accelerometer SET test = " + s + "WHERE _id=" + i
    cursor.execute(sql2)

You should really use SQL parameters instead of string concatenation here; you can then reuse the SQL statement:

sql2 = "UPDATE accelerometer SET test = ? WHERE _id=?"

for i, in data:
    dt = datetime.fromtimestamp(i // 1000)
    cursor.execute(sql2, (i, dt))

where I made two assumptions: that your database driver uses ? as the placeholder syntax (it could be %s instead) and that it natively supports datetime objects (most can these days), so you don’t need to use datetime.strftime() to produce a string first.

The statement reuse can go further, in that the database only has to parse the query once, and only has to produce one query plan; this speeds up repeated executions.

Using SQL parameters has another very important advantage: it prevents SQL injection attacks (where an attacker adds quoting and additional SQL statements). For your specific inputs that is not so much of a concern, but should always be kept in mind.

Answered By: Martijn Pieters

Your data is stored in tuples. And the error message says that strings and tuples can’t be combined as a string, as a tuple isn’t a string.

Instead of:

sql2 = "UPDATE accelerometer SET test = "+ s +"WHERE _id="+i

Try:

sql2 = "UPDATE accelerometer SET test = "+ s +"WHERE _id=%f" % i

I wouldn’t recommend to use %s to build the string, as that could change the format of your floating point values.

Answered By: xph
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.