可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Upon running this script:
#! /usr/bin/env python
import MySQLdb as mdb
import sys
class Test:
def check(self, search):
try:
con = mdb.connect(\'localhost\', \'root\', \'password\', \'recordsdb\');
cur = con.cursor()
cur.execute( \"SELECT * FROM records WHERE email LIKE \'%s\'\", search )
ver = cur.fetchone()
print \"Output : %s \" % ver
except mdb.Error, e:
print \"Error %d: %s\" % (e.args[0],e.args[1])
sys.exit(1)
finally:
if con:
con.close()
test = Test()
test.check(\"test\")
I get an error of:
./lookup
Traceback (most recent call last):
File \"./lookup\", line 27, in <module>
test.check(\"test\")
File \"./lookup\", line 11, in creep
cur.execute( \"SELECT * FROM records WHERE email LIKE \'%s\'\", search )
File \"/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py\", line 187, in execute
query = query % tuple([db.literal(item) for item in args])
TypeError: not all arguments converted during string formatting
I have zero idea why. I\'m trying to do parameterized querys, but it\'s been nothing but a pain. I\'m somewhat new to Python, so it\'s probably an obvious problem.
回答1:
Instead of this:
cur.execute( \"SELECT * FROM records WHERE email LIKE \'%s\'\", search )
Try this:
cur.execute( \"SELECT * FROM records WHERE email LIKE %s\", [search] )
See the MySQLdb documentation. The reasoning is that execute
\'s second parameter represents a list of the objects to be converted, because you could have an arbitrary number of objects in a parameterized query. In this case, you have only one, but it still needs to be an iterable (a tuple instead of a list would also be fine).
回答2:
You can try this code:
cur.execute( \"SELECT * FROM records WHERE email LIKE \'%s\'\", (search,) )
You can see the documentation
回答3:
\'%\' keyword is so dangerous because it major cause of \'SQL INJECTION ATTACK\'.
So you just using this code.
cursor.execute(\"select * from table where example=%s\", (example,))
or
t = (example,)
cursor.execute(\"select * from table where example=%s\", t)
if you want to try insert into table, try this.
name = \'ksg\'
age = 19
sex = \'male\'
t = (name, age, sex)
cursor.execute(\"insert into table values(%s,%d,%s)\", t)
回答4:
cur.execute( \"SELECT * FROM records WHERE email LIKE %s\", (search,) )
I do not why, but this works for me . rather than use \'%s\'
.
回答5:
I don\'t understand the first two answers. I think they must be version-dependent. I cannot reproduce them on MySQLdb 1.2.3, which comes with Ubuntu 14.04LTS. Let\'s try them. First, we verify that MySQL doesn\'t accept double-apostrophes:
mysql> select * from methods limit 1;
+----------+--------------------+------------+
| MethodID | MethodDescription | MethodLink |
+----------+--------------------+------------+
| 32 | Autonomous Sensing | NULL |
+----------+--------------------+------------+
1 row in set (0.01 sec)
mysql> select * from methods where MethodID = \'\'32\'\';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \'9999\'\' \' at line 1
Nope. Let\'s try the example that Mandatory posted using the query constructor inside /usr/lib/python2.7/dist-packages/MySQLdb/cursors.py
where I opened \"con\" as a connection to my database.
>>> search = \"test\"
>>> \"SELECT * FROM records WHERE email LIKE \'%s\'\" % con.literal(search)
\"SELECT * FROM records WHERE email LIKE \'\'test\'\'\"
>>>
Nope, the double apostrophes cause it to fail. Let\'s try Mike Graham\'s first comment, where he suggests leaving off the apostrophes quoting the %s:
>>> \"SELECT * FROM records WHERE email LIKE %s\" % con.literal(search)
\"SELECT * FROM records WHERE email LIKE \'test\'\"
>>>
Yep, that will work, but Mike\'s second comment and the documentation says that the argument to execute (processed by con.literal) must be a tuple (search,)
or a list [search]
. You can try them, but you\'ll find no difference from the output above.
The best answer is ksg97031\'s.
回答6:
According PEP8,I prefer to execute SQL in this way:
cur = con.cursor()
# There is no need to add single-quota to the surrounding of `%s`,
# because the MySQLdb precompile the sql according to the scheme type
# of each argument in the arguments list.
sql = \"SELECT * FROM records WHERE email LIKE %s;\"
args = [search, ]
cur.execute(sql, args)
In this way, you will recognize that the second argument args
of execute
method must be a list of arguments.
May this helps you.
回答7:
The accepted answer by @kevinsa5 is correct, but you might be thinking \"I swear this code used to work and now it doesn\'t,\" and you would be right.
There was an API change in the MySQLdb library between 1.2.3 and 1.2.5. The 1.2.3 versions supported
cursor.execute(\"SELECT * FROM foo WHERE bar = %s\", \'baz\')
but the 1.2.5 versions require
cursor.execute(\"SELECT * FROM foo WHERE bar = %s\", [\'baz\'])
as the other answers state. I can\'t find the change in the changelogs, and it\'s possible the earlier behavior was considered a bug.
The Ubuntu 14.04 repository has python-mysqldb 1.2.3, but Ubuntu 16.04 and later have python-mysqldb 1.3.7+.
If you\'re dealing with a legacy codebase that requires the old behavior but your platform is a newish Ubuntu, install MySQLdb from PyPI instead:
$ pip install MySQL-python==1.2.3