Python supporte-t-il les déclarations préparées par MySQL?
j'ai travaillé sur un projet PHP plus tôt où des déclarations préparées ont fait les requêtes SELECT 20% plus vite.
je me demande si ça marche sur Python? Je n'arrive pas à trouver quoi que ce soit qui indique que c'est le cas ou pas.
7 réponses
réponse directe, Non.
joshperry la réponse de est une bonne explication de ce qu'il fait à la place.
à Partir de eugène y répondre à une question similaire ,
Vérifier la MySQLdb Paquet de Commentaires :
"Paramétrage" se fait dans MySQLdb par s'échapper les chaînes et ensuite les interpolant aveuglément dans la requête, au lieu d'utiliser le API MYSQL_STMT. En conséquence, les chaînes unicode doivent passer par deux représentations intermédiaires (chaîne codée, chaîne codée échappée) ) avant qu'ils ne soient reçus par la base de données.
donc la réponse est: non, ce n'est pas le cas.
la plupart des langues fournissent un moyen de faire des déclarations paramétrées génériques, Python n'est pas différent. Lorsqu'une requête paramétrée est utilisée, les bases de données qui prennent en charge la préparation des déclarations le feront automatiquement.
en python une requête paramétrée ressemble à ceci:
cursor.execute("SELECT FROM tablename WHERE fieldname = %s", [value])
le style de paramétrage spécifique peut être différent selon votre pilote, vous pouvez importer votre module db et ensuite faire un print yourmodule.paramstyle
.
De PEP-249 :
paramstyle
String constant stating the type of parameter marker formatting expected by the interface. Possible values are [2]: 'qmark' Question mark style, e.g. '...WHERE name=?' 'numeric' Numeric, positional style, e.g. '...WHERE name=:1' 'named' Named style, e.g. '...WHERE name=:name' 'format' ANSI C printf format codes, e.g. '...WHERE name=%s' 'pyformat' Python extended format codes, e.g. '...WHERE name=%(name)s'
après un rapide coup d'oeil à travers une méthode execute() d'un objet curseur d'un paquet MySQLdb (une sorte de paquet de facto pour l'intégration avec mysql, je suppose), il semble que (au moins par défaut) il ne fait qu'interpolation de chaîne et citation et non la requête paramétrée réelle:
if args is not None:
query = query % db.literal(args)
si ce n'est pas une interpolation de chaîne, alors qu'est-ce que c'est?
dans le cas de executemany il essaie réellement d'exécuter l'insert / replace comme un simple déclaration d'opposition à l'exécution en boucle. C'est à peu près ça, pas de magie ici, on dirait. Au moins pas dans son comportement par défaut.
EDIT: Oh, je viens de réaliser, que l'opérateur modulo pourrait être dépassé, mais j'ai eu l'impression de tromper et d'attraper la source. Je n'ai pas trouvé d'overriden mod
.
en utilisant L'Interface SQL comme suggéré par Amit peut fonctionner si vous êtes seulement préoccupé par la performance. Cependant, vous perdez alors la protection contre L'injection SQL qu'un support Python natif pour des instructions préparées pourrait apporter. Python 3 a des modules qui fournissent un support d'instruction préparé pour PostgreSQL. Pour MySQL, "oursql" semble fournir un véritable support de la déclaration préparée (pas simulé comme dans les autres modules).
pour les gens qui essaient juste de comprendre cela, Oui vous pouvez utiliser des déclarations préparées avec Python et MySQL. Il suffit d'utiliser le connecteur MySQL / Python de MySQL lui-même et instancier le curseur droit:
https://dev.mysql.com/doc/connector-python/en/index.html
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html
pas directement lié, mais cette réponse à une autre question à So inclut les détails syntaxiques des requêtes 'templated'. Je dirais que l'auto-évasion serait leur caractéristique la plus importante...
en ce qui concerne la performance, noter la méthode executemany
sur les objets curseur. Il regroupe un certain nombre de requêtes et les exécute toutes en une seule fois, ce qui fait conduire à de meilleures performances.
il y a une Solution!
vous pouvez les utiliser si vous les mettez dans une procédure stockée sur le serveur et les appelez comme ça depuis python...
cursor.callproc(Procedurename, args)
Voici un petit tutoriel sur les procédures Stockées dans mysql et python.
http://www.mysqltutorial.org/calling-mysql-stored-procedures-python /