0
votes

Python ajoute un guillemet simple à mes paramètres de requête

J'essaye d'exécuter cette requête:

cursor.execute("SELECT %s CONCAT(%s, %s) %s FROM Jule", (p, 'DAY_' + _day, as_tmp, 'DAY_' + _day))

en utilisant pymysql. Mon code est:

SELECT '23.34.67.0/22' CONCAT(DAY_31, 'hello') DAY_31 FROM Jule

Mais python ajoute un guillemet simple et renvoie une erreur de syntaxe

"Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à la version de votre serveur MySQL pour la bonne syntaxe à utiliser près de '(' DAY_31 ',' hello ')' DAY_31 'FROM Jule' à la ligne 1"

DAY_31 est une colonne de Jule Schema


4 commentaires

Avez-vous vérifié l'échappement de la chaîne? cette question vous oriente-t-elle dans la bonne direction? Ce que je veux dire par échappement de chaîne, c'est qu'il semble y avoir un échappement automatique indésirable effectué sur votre chaîne et qu'il pourrait y avoir un moyen d'éviter cela dans la fonction cursor.execute.


il renvoie "Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à la version de votre serveur MySQL pour la bonne syntaxe à utiliser near '(' \\ 'DAY_31 \\' ',' 6762 ')' \\ 'DAY_31 \\ '' FROM Jule 'à la ligne 1 "


ok, il manque une virgule 'cursor.execute ("SELECT% s, CONCAT (% s,% s)% s FROM Jule", (p,' DAY_ '+ day, as_tmp,' DAY ' + _jour))


Ne devrait-il pas être: SELECT '23 .34.67.0 / 22 ', CONCAT (DAY_31,' hello '), DAY_31 FROM Jule , c'est-à-dire que vous ne manquez pas de virgules?


3 Réponses :


0
votes

Si la mémoire est bonne, ? à la place de % s pourrait faire l'affaire.


1 commentaires

merci pour la réponse, mais il renvoie 'TypeError: tous les arguments ne sont pas convertis lors du formatage de la chaîne



0
votes

En fait, ce qui se passe n'a rien à voir avec cursor.execute . C'est juste la façon dont vous formatez la chaîne en python.

Nous devons d'abord noter que% s% d peut être spécifique à SQL, et que ceux-ci peuvent également être utilisés en python pour le formatage de chaîne.

Donc, en tenant compte de cela, je pense que vous n'avez pas besoin d'utiliser% s pour le formatage des chaînes (ce qui en plus n'aide pas à la lisibilité). Et comme vous êtes cursor.execute directement dans votre base de données, vous pouvez formater votre chaîne tout de suite en python.

Petite vérification pour voir ce qui se passe:

cursor.execute(f"SELECT '{p}' CONCAT(DAY_{_day}, '{as_tmp}') DAY_{_day} FROM Jule")

Si vous formatez avec une f-string, vous augmenterez la lisibilité, et vous devriez vous débarrasser de votre problème avec les guillemets

print(f"SELECT '{p}' CONCAT(DAY_{_day}, '{as_tmp}') DAY_{_day} FROM Jule")
# output
# SELECT '23.34.67.0/22' CONCAT(DAY_3, 'hello') DAY_3 FROM Jule

Ainsi, le la solution pourrait être:

p = "23.34.67.0/22"
as_tmp = "hello"
_day = "3"
print("SELECT %s CONCAT(%s, %s) %s FROM Jule", (p, 'DAY_' + _day, as_tmp, 'DAY_' + _day))
# output
# SELECT %s CONCAT(%s, %s) %s FROM Jule ('23.34.67.0/22', 'DAY_3', 'hello', 'DAY_3')
# ^^^^ so this is what is being sent in cursor.execute (with all the quotes and so on)


2 commentaires

Merci pour la réponse, mais le problème était une virgule manquante. Quoi qu'il en soit je garderai à l'esprit ta réponse


Cette réponse laisse l'application sujette à l'injection SQL si as_tmp pourrait provenir de l'extérieur de l'application. L'approche d'origine était correcte pour les valeurs de données de chaîne, mais il n'y a aucun moyen d'éviter l'épissage des noms de champ comme vous l'avez suggéré.



0
votes

La raison pour laquelle vous vous retrouvez avec des guillemets est que cursor.execute ajoute ces valeurs autour que vous passez en arguments. Ceci est tout à fait approprié pour votre deuxième argument, car si la valeur «bonjour» était insérée dans la requête telle quelle, vous vous retrouveriez avec une requête comme celle-ci:

cursor.execute(f"SELECT %s, CONCAT({'DAY_'+_day}, %s) {'DAY_'+_day} FROM Jule", (p, as_tmp))

et vous auriez des erreurs vous disant que MySQL ne peut pas identifier à quoi bonjour devrait se référer.

De toute évidence, cela n'est pas approprié pour les situations où vous voulez passer des noms de champs strong>, ou toute autre partie de la requête qui n'est pas une valeur de chaîne primitive. Dans ces cas, vous devrez les épisser dans votre chaîne avant d'exécuter la requête. Une façon de le faire est d'utiliser des f-strings , mais il y a d'autres alternatives également. Voici votre ligne cursor.execute avec les noms de champs épissés en utilisant des chaînes f:

 SELECT '23.34.67.0/22' CONCAT(DAY_31, hello) DAY_31 FROM Jule

Notez que j'ai supprimé le ' DAY _ '+ _ day dans la liste des arguments également.

Remarque importante:

Bien que cela devrait fonctionner comme ça (même si je pense que vous avait également besoin d'une virgule supplémentaire après SELECT '23 .34.67.0 / 22 ', que j'ai ajouté dans l'exemple ci-dessus), il est très important que si day a une valeur qui provient de l'extérieur de votre application (par exemple, transmis par un utilisateur dans un champ de formulaire) que vous vous assurez qu'il est exactement dans le format que vous voulez avant de le raccorder à votre requête. Vérifier que la valeur de la chaîne est un entier pourrait être un moyen de le faire. La raison pour laquelle c'est important est que sans cela, votre application pourrait être sujette à injection SQL a >, ce qui permettrait potentiellement aux utilisateurs d'exécuter du SQL arbitraire sur votre base de données. Si la valeur de day est calculée uniquement par votre application, vous ne devriez pas avoir à vous en préoccuper.


0 commentaires