IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

erreur de guillemet lors de l'insertion dans SQL [Python 3.X]


Sujet :

Python

  1. #21
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 334
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 334
    Par défaut
    Citation Envoyé par figuedi Voir le message
    J'ai trouvé la solution sur la toile il fallait mettre des ' autour %s quand tu attends des strings et en effet j'ai la même erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cursor.execute("""INSERT INTO jeu (Nom,Force)
                       VALUES ('%s',%s)""" % (nom.Nom,nom.F))
    [/CODE]


    Tu trouves sur la toile ce qu'il ne faut pas faire, et malgré mes dires, cela ne te pose aucun problème

    https://www.psycopg.org/docs/usage.html#sql-injection
    Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.
    The correct way to pass variables in a SQL command is using the second argument of the execute() method

    ...
    The Python string operator % must not be used: the execute() method accepts a tuple or dictionary of values as second parameter. Never use % or + to merge values into queries:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> cur.execute("INSERT INTO numbers VALUES (%s, %s)" % (10, 20)) # WRONG
    >>> cur.execute("INSERT INTO numbers VALUES (%s, %s)", (10, 20))  # correct
    Qui t'a menacé de mort pour utiliser ce code trouvé sur le web ? Ils sont pourtant clair !

    -------
    je te l'avais dit que ton problème était maintenant coté sql et plus python, mais tu préfères utiliser du mauvais code pris au hasard…
    Note: existe un forum sql ici.


    ################################################

    Ne le prends pas pour toi.

    j'ai connu les "belles" années php : les codeurs commençaient par php et comme toi, préféraient copier un code douteux (ils n'avaient pas le niveau pour le savoir) que de lire les doc. Résultat, php a entrainé une décennie de mauvaises pratiques. Maintenant, les codeurs débutent avec python, il ne faut pas que python devienne ce même nid aux mauvaises pratiques.

  2. #22
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 018
    Par défaut
    Citation Envoyé par figuedi Voir le message
    Et en fait c'était le nom du champ Force qui est réservé et qui me bloquait.
    Oui, mais ça c'est pas super grave, car si par inadvertance ou méconnaissance (ou bien parce que tu veux vraiment l'appeler comme ça) tu te retrouves avec un nom de colonne qui est un mot-clef SQL ou un mot réservé (pour MySQL 8.0 ils sont consultables ici), il suffit d'encadrer le nom de colonne avec des backticks, comme ceci: INSERT INTO jeu (Nom, `Force`, ... pour lever l'ambiguïté.

    Nota bene (et spiritus sancti): Dans le jargon des bases de données, on ne dit pas "un champ" mais "une colonne".

    Citation Envoyé par figuedi
    J'ai trouvé la solution sur la toile il fallait mettre des ' autour %s quand tu attends des strings et en effet j'ai la même erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cursor.execute("""INSERT INTO jeu (Nom,Force)
                      VALUES ('%s',%s)""" % (nom.Nom,nom.F))
    Non!

    Tu es tombé dans un piège: celui du double sens de %s dans ce cas précis:
    • En dehors du SQL, %s est utilisé dans les chaînes formatées en Python:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      nom = 'Laurence'
      plat = 'blanquette de veau'
      myFormattedString = '%s a mangé trop de %s'
      print(myFormattedString%(nom, plat))
      (Le % marque qu'on applique un tuple sur la chaîne formatée pour qu'elle remplace les placeholders %s par les valeurs du tuple).
      Ce qui est pratique lorsqu'on veut répéter x fois la même chaîne avec des noms ou des plats différents.
    • Par contre dans le cadre SQL avec la méthode execute, %s est tout autre chose et il ne faut pas le confondre avec le précédent. C'est toujours un placeholder, mais on ne lui applique pas le tuple avec le signe % pour fabriquer un chaîne et tout passer en un seul paramètre. On utilise 2 paramètres.
      Ça permet de séparer la requête SQL (disons son squelette), des données qui vont y figurer. C'est pourquoi la méthode execute dispose de deux paramètres (séparés d'une virgule):
      • le premier pour le squelette
      • le second pour les données
      .
      L'intérêt de cette séparation en deux paramètres distinctes est justement de s'affranchir des problèmes de quotes, d'échappements et que sais-je encore... car c'est la méthode execute qui s'en chargera toute seule comme une grande!


    Il faut donc écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cursor.execute("""INSERT INTO jeu (Nom, `Force`)
                      VALUES (%s, %s)""", (nom.Nom, nom.F))
    Juste pour illustrer, en PHP on fait exactement la même chose sauf que le placeholder n'est pas %s mais ?:
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $stmt = $mysqli->prepare('INSERT INTO jeu (Nom,`Force`) VALUES (?,?)');
    $stmt->execute([$nom->Nom, $nom->F]);
    Le squelette de la requête et les données sont séparés.

    Et pour les chaînes formatées:
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $nom = 'Laurence';
    $plat = 'blanquette de veau';
    $myFormattedString = '%s a mangé trop de %s';
    printf($myFormattedString, $nom, $plat);

  3. #23
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    712
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 712
    Par défaut
    Accessoirement: perdez cette sale habitude d'utiliser le compte root pour la DB. Créez un utilisateur restreint avec droits read/write seulement sur sa DB.
    Au cas où votre application est compromise (injection SQL), vous ne pourrez peut-être pas empêcher un attaquant d'exfiltrer votre DB, mais vous pourriez l'empêcher d'aller plus loin et prendre le contrôle total du serveur.
    L'utilisateur root a certains droits intéressants pour un hacker comme la possibilité de lire et écrire des fichiers, ce qui est utile pour uploader un webshell, consulter des fichiers de configuration sensibles ou ce genre de truc.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 17
    Dernier message: 09/11/2023, 14h38
  2. Réponses: 11
    Dernier message: 16/05/2014, 16h52
  3. Réponses: 7
    Dernier message: 12/05/2010, 15h33
  4. Récupération message d'erreur lors d'une insertion dans une BDD
    Par LoDev dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 22/12/2007, 19h11
  5. [MySQL] Erreur lors de l'insertion dans ma base de doneés
    Par ANISSS dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 15/11/2006, 12h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo