Partage
  • Partager sur Facebook
  • Partager sur Twitter

Requête préparée

Double Update

    24 janvier 2017 à 11:46:49

    Bonjour,

    J'ai un problème avec une requête préparée avec un double update.

    Sur un fichier php seul (de test donc) mes requetes s'exécutent toutes.
    Si je les intègre au programme, ça ne fonctionne plus.

    La différence évidente est que dans le fichier test, les variables sont déclarées en dur ($nom="truc";..) alors que dans le programme elles sont récupérées ($nom = $_POST['le_nom'];....) . Un echo renvoie bien $nom, donc ça passe bien.

    $marequete="UPDATE `table` SET `valeur`=".$x." WHERE `table`.`Nom`='variable1'; UPDATE `table` SET `valeur`=".$y." WHERE `table`.`Nom`='variable2';";

    Au mieux, j'ai une erreur de syntaxe, au pire, aucun résultat.

    Pouvez vous m'aider svp ?
    Cdt

    • Partager sur Facebook
    • Partager sur Twitter
      24 janvier 2017 à 12:02:33

      Le vrai code ?

      Tu mentionnes :

      • $nom et ce que tu nous montres c'est $x/$y
      • une requête préparée mais il n'y a pas de marqueur (et une vraie requête préparée c'est une requête pas 2, le multi-statement ne serait pas accepté)
      • une erreur de syntaxe mais tu ne la donnes pas pour autant

      Il manque les quotes pour le SQL ? Encore que si la requête était correctement préparée au lieu d'injecter tes données par concaténation, ce problème ne se poserait pas et ça ne te vaudrait pas non plus des injections SQL ...

      -
      Edité par julp 24 janvier 2017 à 12:04:07

      • Partager sur Facebook
      • Partager sur Twitter
        24 janvier 2017 à 12:15:58

        Bonjour

        Pour information ce que tu écris est tout sauf une requête préparée ...

        Tu en trouveras ici

        • Partager sur Facebook
        • Partager sur Twitter
        Un petit +1 si je vous ai aidé est toujours appréciable :).     Ps : on ne dit pas "à ledisciple", mais bien "au disciple".
          24 janvier 2017 à 12:33:05

          OK sur le principe de la requête préparée, je suis d'accord.

          Mon problème, c'est de mettre a jour deux champs (c'est pour la compréhension, parce qu'en fait, il y en a plus que ça) dans une table en disant :

          mettre a jour avec la valeur v1 la ligne dont le champs nom = nom1

          en meme temps que

          mettre a jour avec la valeur v2 la ligne dont le champs nom = nom2

          J'aurais plus vite fait de faire une table avec x champs ou j'indiquerai pour chaque une valeur, mais ça n'est pas très économique comme solution.

                  $CONNEXION = new mysqli($dbhost, $dbuser, $dbpass, $base);

                  $query = "UPDATE table SET val='val1' WHERE nom='nom1';UPDATE table SET val='val2' WHERE nom='nom2';";

                  if ($stmt = $CONNEXION->prepare($query)) {
                      /* Exécution de la requête */
                      $stmt->execute();
                      echo("Enregistrement effectué<BR>");
                  }
                  $stmt->close();

          On part de ca en fait.

          • Partager sur Facebook
          • Partager sur Twitter
            24 janvier 2017 à 13:35:39

            en meme temps

            Je demande à voir si c'est vraiment en même temps (plutôt traité à la suite directe et dans la même transaction en auto-commit).

            De toute façon, ta requête préparée ne sert à rien là et ne fonctionnera pas (une vraie requête préparée ne peut pas être constituée de plusieurs instructions/requêtes - pas de ;). Si tu avais X update à faire, tu prépares ton update, débutes une transaction et l'exécute X fois.

            Cf la doc de mysql_stmt_prepare (la fonction C qui est utilisée derrière par PHP)

            26.8.11.21 mysql_stmt_prepare() The string must consist of a single SQL statement. You should not add a terminating semicolon (;) or \g to the statement.

            Tu peux toujours tout mettre dans une requête multi-statement et l'exécuter par mysqli_multi_query mais c'est plus complexe à implémenter (si c'est pour se retrouver avec des injections SQL, ce n'est pas la peine) et la requête en devient inutilement longue/répétitive (possible d'atteindre le max_allowed_packet ?).

            Avec un autre SGBD, on aurait certainement pu faire ça en une seule requête en injectant les valeurs en sous-requête. Type pour PostgreSQL :

            UPDATE table
                SET val = t.val
                WHERE nom = t.nom
            FROM (
                VALUES('val1', 'nom1'), ('val2', 'nom2')
            ) t(val, nom);
            

            -
            Edité par julp 24 janvier 2017 à 13:59:50

            • Partager sur Facebook
            • Partager sur Twitter
              24 janvier 2017 à 14:05:00

              L'idée se rapprocherait de ça

              $query="UPDATE table SET val=?? WHERE nom=??;

              $params1 = array("val1","val2");
              $params2 = array("nom1","nom2");

              mysqli_prepared_query($link,$query,"ss",$params1,$params2)

              Les ?? sont mes inconnues (params)

              et pour mysqli_prepared_query j'extrapole en ajoutant $params2.. mais suis pas certan que ca fonctionne comme ça.

              • Partager sur Facebook
              • Partager sur Twitter
                24 janvier 2017 à 14:15:19

                C'est justement à ça que sert une requête préparée ...

                $values = [
                    [ 'val1', 'nom1', ],
                    [ 'val2', 'nom2', ],
                ];
                $stmt = $link->prepare('UPDATE table SET val = ? WHERE nom = ?');
                $stmt->bind_param('ss', $line[0], $line[1]);
                foreach ($values as $line) {
                    $stmt->execute();
                }
                

                (pas testé)

                • Partager sur Facebook
                • Partager sur Twitter
                  24 janvier 2017 à 15:28:39

                  Pas de $stmt->close(); en suite ?

                  Ni de mysqli_query ???

                  Mon code est le suivant :

                  $values = [
                      [ $colonne, 'NbCol', ],
                      [ $lienaffich, 'LienParPage', ],
                  ];

                  echo("Values = ".$values."");  // retourne uniquement    Array    sans rien d'autre

                  $stmt = $connexion->prepare('UPDATE parametres SET Par_NumVal=? WHERE Par_Nom=?');   // $link remplacé par $connexion
                  $stmt->bind_param('ss', $line[0], $line[1]);
                  foreach ($values as $line) {
                      $stmt->execute();
                  }


                  Ce code ne retourne ni erreur, ni modification de la table.

                  A quoi ser 'ss' dans bind_param ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    24 janvier 2017 à 15:59:42

                    Pas de $stmt->close(); en suite ?

                    PHP s'en charge automatiquement en fin de script donc pas obligé de le faire explicitement.

                    Ni de mysqli_query ???

                    Si la requête est préparée, on ne fait que l'exécuter. mysql_query c'est pour exécuter une requête non-préparée.

                    A quoi ser 'ss' dans bind_param ?

                    A la même chose que dans ton mysqli_prepared_query j'imagine ? (sinon voir sa doc)

                    retourne uniquement Array sans rien d'autre

                    C'est normal, ça n'a pas de sens d'afficher un array. PHP se contente alors de renvoyer la chaîne "Array".

                    A priori, on ne peut pas directement utiliser :

                    $stmt->bind_param('ss', $line[0], $line[1]);
                    foreach ($values as $line) {
                    

                    Mais ceci a l'air de fonctionner :

                    $stmt->bind_param('ss', $nom, $val);
                    foreach ($values as list($nom, $val)) {
                    

                    -
                    Edité par julp 24 janvier 2017 à 16:58:14

                    • Partager sur Facebook
                    • Partager sur Twitter
                      24 janvier 2017 à 16:48:09

                      Yala !!!!!!

                      OK un grand merci.

                      La il va me falloir 2 semaines de repos au moins :-)

                      Bon, ca marche, c'est nickel.

                      Merci, merci !!!!!

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Requête préparée

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown