Lors de l'exécution de ce 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")
Je reçois une erreur de:
./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
Je n'ai aucune idée pourquoi. J'essaie de faire des requêtes paramétrées, mais ça n'a été qu'une douleur. Je suis un peu nouveau dans Python, donc c'est probablement un problème évident.
Au lieu de cela:
cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )
Essaye ça:
cur.execute( "SELECT * FROM records WHERE email LIKE %s", [search] )
Voir la documentation MySQLdb . Le raisonnement est que le second paramètre de execute
représente une liste des objets à convertir, car vous pourriez avoir un nombre arbitraire d'objets dans une requête paramétrée. Dans ce cas, vous n’en avez qu’un, mais il faut tout de même que ce soit un itératif (un tuple au lieu d’une liste conviendrait également).
Vous pouvez essayer ce code:
cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", (search,) )
Vous pouvez voir la documentation
Le mot clé '%' est si dangereux parce qu'il est la principale cause de 'SQL INJECTION ATTACK'.
Donc vous utilisez simplement ce code.
cursor.execute("select * from table where example=%s", (example,))
ou
t = (example,)
cursor.execute("select * from table where example=%s", t)
si vous voulez essayer d’insérer dans un tableau, essayez ceci.
name = 'ksg'
age = 19
sex = 'male'
t = (name, age, sex)
cursor.execute("insert into table values(%s,%d,%s)", t)
cur.execute( "SELECT * FROM records WHERE email LIKE %s", (search,) )
Je ne sais pas pourquoi, mais cela fonctionne pour moi. plutôt que d'utiliser '%s'
.
J'ai rencontré cette erreur lors de l'exécution de SELECT * FROM table;
J'ai tracé l'erreur sur la ligne du curseur.py.
if args is not None:
if isinstance(args, dict):
nargs = {}
for key, item in args.items():
if isinstance(key, unicode):
key = key.encode(db.encoding)
nargs[key] = db.literal(item)
args = nargs
else:
args = Tuple(map(db.literal, args))
try:
query = query % args
except TypeError as m:
raise ProgrammingError(str(m))
Étant donné que je saisis des paramètres supplémentaires, je me suis débarrassé de toute la branche "if args ...". Maintenant ça marche.
La réponse acceptée par @ kevinsa5 est correcte, mais vous pourriez penser: "Je jure que ce code utilisé fonctionne et maintenant il ne fonctionne pas", et vous auriez raison.
Une modification de l'API dans la bibliothèque MySQLdb s'est produite entre 1.2.3 et 1.2.5. Les versions 1.2.3 supportées
cursor.execute("SELECT * FROM foo WHERE bar = %s", 'baz')
mais les versions 1.2.5 nécessitent
cursor.execute("SELECT * FROM foo WHERE bar = %s", ['baz'])
comme le dit l'autre réponse. Je ne trouve pas le changement dans les changelogs, et il est possible que le comportement précédent ait été considéré comme un bogue.
Le référentiel Ubuntu 14.04 a python-mysqldb 1.2.3, mais Ubuntu 16.04 et les versions ultérieures ont python-mysqldb 1.3.7+.
Si vous avez affaire à une base de code héritée qui requiert l'ancien comportement mais que votre plate-forme est une Ubuntu nouvelle génération, installez MySQLdb à partir de PyPI:
$ pip install MySQL-python==1.2.3
Je ne comprends pas les deux premières réponses. Je pense qu'ils doivent être dépendants de la version. Je ne peux pas les reproduire sur MySQLdb 1.2.3, qui est fourni avec Ubuntu 14.04LTS. Essayons les. Tout d'abord, nous vérifions que MySQL n'accepte pas les doubles 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
Nan. Essayons l'exemple que Mandatory a publié à l'aide du constructeur de la requête dans /usr/lib/python2.7/dist-packages/MySQLdb/cursors.py
où j'ai ouvert "con" en tant que connexion à ma base de données.
>>> search = "test"
>>> "SELECT * FROM records WHERE email LIKE '%s'" % con.literal(search)
"SELECT * FROM records WHERE email LIKE ''test''"
>>>
Non, les doubles apostrophes la font échouer. Essayons le premier commentaire de Mike Graham, dans lequel il suggère de laisser les apostrophes citant les% s:
>>> "SELECT * FROM records WHERE email LIKE %s" % con.literal(search)
"SELECT * FROM records WHERE email LIKE 'test'"
>>>
Oui, cela fonctionnera, mais le deuxième commentaire de Mike et la documentation indiquent que l'argument à exécuter (traité par con.literal) doit être un Tuple (search,)
ou une liste [search]
. Vous pouvez les essayer, mais vous ne trouverez aucune différence avec le résultat ci-dessus.
La meilleure réponse est celle de ksg97031.
Selon PEP8, je préfère exécuter SQL de cette façon:
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)
De cette manière, vous reconnaîtrez que le deuxième argument args
de la méthode execute
doit être une liste d'arguments.
Puisse cela vous aider.