Commandes désynchronisées; vous ne pouvez pas exécuter cette commande maintenant

94

J'essaye d'exécuter mon code PHP, qui appelle deux requêtes MySQL via mysqli, et j'obtiens l'erreur "Commandes désynchronisées; vous ne pouvez pas exécuter cette commande maintenant".

Voici le code que j'utilise

<?php
$con = mysqli_connect("localhost", "user", "password", "db");
if (!$con) {
    echo "Can't connect to MySQL Server. Errorcode: %s\n". Mysqli_connect_error();
    exit;
}
$con->query("SET NAMES 'utf8'");
$brand ="o";
$countQuery = "SELECT ARTICLE_NO FROM AUCTIONS WHERE upper(ARTICLE_NAME) LIKE % ? %";
if ($numRecords = $con->prepare($countQuery)) {
    $numRecords->bind_param("s", $brand);
    $numRecords->execute();
    $data = $con->query($countQuery) or die(print_r($con->error));
    $rowcount = $data->num_rows;
    $rows = getRowsByArticleSearch("test", "Auctions", " ");
    $last = ceil($rowcount/$page_rows);
}  else {

print_r($con->error);
}
foreach ($rows as $row) {
    $pk = $row['ARTICLE_NO'];
    echo '<tr>' . "\n";
    echo '<td><a href="#" onclick="updateByPk(\'Layer2\', \'' . $pk . '\')">'.$row['USERNAME'].'</a></td>' . "\n";
    echo '<td><a href="#" onclick="updateByPk(\'Layer2\', \'' . $pk . '\')">'.$row['shortDate'].'</a></td>' . "\n";
    echo '<td><a href="#" onclick="deleterec(\'Layer2\', \'' . $pk . '\')">DELETE RECORD</a></td>' . "\n";
    echo '</tr>' . "\n";
}
function getRowsByArticleSearch($searchString, $table, $max) {
    $con = mysqli_connect("localhost", "user", "password", "db");
    $recordsQuery = "SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME, date_format(str_to_date(ACCESSSTARTS, '%d/%m/%Y %k:%i:%s'), '%d %m %Y' ) AS shortDate FROM AUCTIONS WHERE upper(ARTICLE_NAME) LIKE '%?%' ORDER BY str_to_date(ACCESSSTARTS, '%d/%m/%Y %k:%i:%s')" . $max;
    if ($getRecords = $con->prepare($recordsQuery)) {
        $getRecords->bind_param("s", $searchString);
        $getRecords->execute();
        $getRecords->bind_result($ARTICLE_NO, $USERNAME, $ACCESSSTARTS, $ARTICLE_NAME, $shortDate);
        while ($getRecords->fetch()) {
            $result = $con->query($recordsQuery);
            $rows = array();
            while($row = $result->fetch_assoc()) {
                $rows[] = $row;
            }
            return $rows;
        }
    }
}

J'ai essayé de lire à ce sujet, mais je ne sais pas quoi faire. J'ai lu sur le résultat du magasin et le résultat gratuit, mais ceux-ci n'ont fait aucune différence lors de leur utilisation. Je ne sais pas exactement à quel point cette erreur est causée et j'aimerais savoir pourquoi elle est causée et comment y remédier.

En suivant mes instructions de débogage, la première boucle if pour countQuery n'est même pas entrée, en raison d'une erreur dans ma syntaxe SQL proche de '% ? %'. Cependant, si je sélectionne simplement *au lieu d'essayer de limiter en fonction d'une clause LIKE, j'obtiens toujours une erreur de désynchronisation de la commande.

Joshxtothe4
la source

Réponses:

115

Vous ne pouvez pas avoir deux requêtes simultanées car mysqli utilise par défaut des requêtes non tamponnées (pour les instructions préparées; c'est le contraire pour vanilla mysql_query). Vous pouvez soit récupérer le premier dans un tableau et le parcourir en boucle, soit dire à mysqli de tamponner les requêtes (en utilisant $stmt->store_result()).

Voir ici pour plus de détails.

HoLyVieR
la source
3
Je suis d'accord, mysqli est un peu endommagé au cerveau. Il fait cependant ce qu'il faut avec le pilote mysql PDO.
17
Vous pouvez avoir deux requêtes simultanées - il vous suffit d'exécuter $stmt->store_result();je pense que votre réponse devrait clarifier cela.
Ombre
3
Cela me prend du temps pour trouver ces informations - nulle part où elles ne sont facilement affichées. Merci. Je viens $select_stmt->close();de séparer mes requêtes avec pour les diviser (pas simultanées mais procédurales
n34_panda
@flussence, Vous avez déclaré que "mysqli utilise par défaut des requêtes sans tampon". Alors, comment pouvons-nous le faire faire autrement?
Pacerier
1
Je sais que cela semble étrange, mais j'ai eu cette erreur lors de l'exécution d'une requête avec mysqli_query violant une clé étrangère ... donc si cela arrive à quelqu'un, vérifiez que votre requête INSERT ne viole aucune clé étrangère
lucaferrario
34

J'ai résolu ce problème dans mon application C - voici comment je l'ai fait:

  1. Citant des forums mysql:

    Cette erreur se produit lorsque vous terminez votre requête avec un délimiteur point-virgule dans l'application . S'il est nécessaire de terminer une requête avec un séparateur point-virgule lors de son exécution à partir de la ligne de commande ou dans le navigateur de requêtes, supprimez le délimiteur de la requête dans votre application.

  2. Après avoir exécuté ma requête et traité les résultats [API C: mysql_store_result()], j'effectue une itération sur tout autre résultat potentiellement en attente qui se produit via l'exécution de plusieurs instructions SQL telles que deux ou plusieurs instructions select (dos à dos sans traiter les résultats).

    Le fait est que mes procédures ne renvoient pas plusieurs résultats mais la base de données ne le sait pas tant que je n'exécute pas: [C API: mysql_next_result()]. Je fais cela en boucle (pour faire bonne mesure) jusqu'à ce qu'il retourne non nul. C'est à ce moment que le gestionnaire de connexion actuel sait qu'il est correct d'exécuter une autre requête (je cache mes gestionnaires pour minimiser la surcharge de connexion).

    C'est la boucle que j'utilise:

    for(; mysql_next_result(mysql_handler) == 0;) 
      /* do nothing */;
    

Je ne connais pas PHP mais je suis sûr qu'il a quelque chose de similaire.

tracy.brown
la source
11
C'était tout pour moi. En PHP, je viens d'ajouter: while (mysqli_next_result ($ con));
Josh
Merci pour la réponse qui a résolu mon problème. J'ai supprimé le délimiteur et cela fonctionne. Je n'ai pas libéré (récupéré) ou stocké mes résultats, mais j'ai fermé le curseur et reconstruit une fois que j'ai terminé une instruction de requête.
Chen Xie
@Josh, comment faire ça dans l' mysqlextension héritée ?
Pacerier
1
La suppression du point-virgule à la fin de la requête a corrigé le problème «Commandes non synchronisées; vous ne pouvez pas exécuter cette commande maintenant» lors de l'utilisation de Python MySQLdb.
Genome
17

J'ai eu aujourd'hui le même problème, mais uniquement en travaillant avec une procédure stockée. Cela fait que la requête se comporte comme une requête multiple, vous devez donc «consommer» les autres résultats disponibles avant d'effectuer une autre requête.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
staline beltran
la source
C'est un point important: les procédures stockées renvoient un jeu de résultats en plus de tout jeu de résultats que le code du SP peut générer. Vous devez gérer cela ou obtenir cette erreur: stackoverflow.com/a/2315229/4495850
Richard
11

J'appelle cette fonction à chaque fois avant d'utiliser $ mysqli-> query Fonctionne également avec les procédures stockées.

function clearStoredResults(){
    global $mysqli;

    do {
         if ($res = $mysqli->store_result()) {
           $res->free();
         }
        } while ($mysqli->more_results() && $mysqli->next_result());        

}
Juergen
la source
5

Une fois que vous avez utilisé

stmt->execute();

Vous POURRIEZ fermer à utiliser une autre requête.

stmt->close();

Ce problème me traquait pendant des heures. J'espère que cela réparera le vôtre.

Carl James
la source
1
Il n'est pas nécessaire de fermer la déclaration. Comme @stalinbeltran a répondu ci-dessus, nous devons "consommer" le résultat d'une instruction avant d'en préparer une autre. Donc, $stmt1->execute(); $stmt2=$conn->prepare(...)donnerait cette erreur, mais $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)fonctionnerait très bien.
Jay Dadhania
Bro ça m'a aidé à te remercier. Pour tous ceux qui disent ceci et cela, j'ai utilisé mysqli_prepare deux fois avant de fermer le premier. Ça marche.
Abhinash Majhi
2

J'utilise CodeIgniter. Un serveur OK ... celui-ci probablement plus ancien ... De toute façon en utilisant

$this->db->reconnect();

Corrigé.

normand
la source
7
Comment cela résout-il le problème?
Jeremy J Starcher
4
@Norman, cela ne "résout" pas le problème. Il l' évite simplement en jetant toute la connexion et en se reconnectant à nouveau. Cela n'a aucun sens du point de vue des performances.
Pacerier
1

Le problème est la bibliothèque C du client MySQL, sur laquelle la plupart des API MySQL sont construites. Le problème est que la bibliothèque C ne prend pas en charge l'exécution simultanée de requêtes, de sorte que toutes les API créées en plus ne le font pas non plus. Même si vous utilisez des requêtes sans tampon. C'est l'une des raisons pour lesquelles l'API MySQL asynchrone a été écrite. Il communique directement avec le serveur MySQL en utilisant TCP et le protocole filaire prend en charge les requêtes simultanées.

Votre solution consiste soit à modifier l'algorithme pour ne pas avoir à avoir les deux en cours à la fois, soit à les changer pour utiliser des requêtes tamponnées, ce qui est probablement l'une des raisons originales de leur existence dans la bibliothèque C (l'autre est de fournir une sorte de curseur).

statique
la source
1
Je n'ai pas besoin d'avoir les deux en cours à la fois, je suis heureux que countQuery se termine complètement avant ma deuxième requête, mais je ne sais pas comment empêcher countQuery d'être en cours
Vous ne récupérez aucune donnée de countQuery, c'est pourquoi il est toujours «en cours». Soit récupérer toutes les lignes, soit le changer en SELECT COUNT (ARTICLE_NO) et obtenir cette ligne. Ensuite, votre deuxième requête s'exécutera.
staticsan
Quand vous dites "l'API MySQL asynchrone", à quelle API parlez-vous? De plus, je ne comprends pas votre conclusion. Ce "problème" peut être résolu sans que l'API soit asynchrone.
Pacerier
1
Pour être honnête @Pacerier, je ne suis plus sûr de ce que je voulais dire non plus! Beaucoup de choses se sont passées en six ans dans la connectivité MySQL, donc tout ce à quoi je pensais faire référence a probablement été renommé et / ou incorporé dans un autre nouveau pilote.
staticsan
1

pour résoudre ce problème, vous devez stocker les données de résultat avant de les utiliser

$numRecords->execute();

$numRecords->store_result();

c'est tout

Nader Ben Mabrouk
la source
1

Autre cause: store_result () ne peut pas être appelé deux fois.

Par exemple, dans le code suivant, l'erreur 5 est imprimée.

<?php

$db = new mysqli("localhost", "something", "something", "something");

$stmt = $db->stmt_init();
if ($stmt->error) printf("Error 1 : %s\n", $stmt->error);

$stmt->prepare("select 1");
if ($stmt->error) printf("Error 2 : %s\n", $stmt->error);

$stmt->execute();
if ($stmt->error) printf("Error 3 : %s\n", $stmt->error);

$stmt->store_result();
if ($stmt->error) printf("Error 4 : %s\n", $stmt->error);

$stmt->store_result();
if ($stmt->error) printf("Error 5 : %s\n", $stmt->error);

(Cela peut ne pas être pertinent pour l'exemple de code d'origine, mais cela peut être pertinent pour les personnes cherchant des réponses à cette erreur.)

David G.
la source
1

Voici quel était mon problème !!!

La liaison des paramètres était "dynamique", donc j'avais une variable qui définit les paramètres des données afin d'utiliser bind_param . Donc, cette variable était fausse, mais au lieu de lancer une erreur comme «mauvaises données de paramètres», elle dit «désynchronisé bla bla bla», donc j'étais confus ...

Ari Waisberg
la source
0

Je pense que le problème est que vous établissez une nouvelle connexion dans la fonction, puis que vous ne la fermez pas à la fin. Pourquoi n'essayez-vous pas de transmettre la connexion existante et de la réutiliser?

Une autre possibilité est que vous reveniez au milieu d'une récupération en boucle while. Vous ne terminez jamais cette recherche externe.

Paul Tomblin
la source
1
Si je rends $ con global (ce qui est une mauvaise pratique mais devrait fonctionner comme vous le décrivez), j'ai toujours la même erreur.
1
Je ne pense pas qu'avoir une connexion mondiale est une mauvaise pratique
Mathieu J.
0

Vérifiez si vous saisissez correctement tous les paramètres. Il renvoie la même erreur si la quantité de paramètres définis puis passés à la fonction est différente.

Mixtelf
la source
0

Ce n'est pas lié à la question d'origine, mais j'ai eu le même message d'erreur et ce fil est le premier succès dans Google et il m'a fallu un certain temps pour comprendre quel était le problème, il peut donc être utile pour d'autres:

Je n'utilise PAS mysqli, j'utilise toujours mysql_connect J'ai eu quelques requêtes simples, mais UNE requête a provoqué l'échec de toutes les autres requêtes dans la même connexion.

J'utilise mysql 5.7 et php 5.6 j'avais une table avec le type de données "JSON". évidemment, ma version php n'a pas reconnu la valeur de retour de mysql (php ne savait tout simplement pas quoi faire avec le format JSON car le module mysql intégré était trop vieux (du moins je pense))

pour l'instant, j'ai changé le type de champ JSON en texte (car pour l'instant je n'ai pas besoin de la fonctionnalité native mysql JSON) et tout fonctionne bien

mech
la source
0

Si vous utilisez le jeu de résultats Buffered ou Unbuffered pour récupérer des données, vous devez d'abord simplement effacer les données extraites de la mémoire, une fois que vous avez récupéré toutes les données . Comme vous ne pouvez pas exécuter une autre procédure MYSQL sur la même connexion tant que vous n'avez pas effacé la mémoire récupérée. Ajoutez cette fonction ci-dessous à l'extrémité droite de votre script, cela résoudra le problème

$numRecords->close(); or $numRecords->free(); // This clears the referencing memory, and will be ready for the next MYSQL fetch

Référence de la documentation PHP

Kaz
la source
1
Si vous n'avez pas besoin de certains enregistrements, vous ne devriez pas les avoir sélectionnés en premier lieu. Au lieu de simplement les libérer, ne les sélectionnez pas du tout. Et si ce n'est pas le cas et que vous avez récupéré tous les enregistrements sélectionnés, alors il n'y aura pas du tout une telle erreur et il n'est pas nécessaire d'appeler close () ou free (). En ce qui concerne les procédures stockées, il existe une méthode moins barbare, décrite dans les réponses ci
Votre bon sens
0

J'ai rencontré cette erreur en utilisant Doctrine DBAL QueryBuilder.

J'ai créé une requête avec QueryBuilder qui utilise des sous-sélections de colonnes, également créées avec QueryBuilder. Les sous-sélections ont été créées uniquement via $queryBuilder->getSQL()et non exécutées. L'erreur s'est produite lors de la création de la deuxième sous-sélection. En exécutant provisoirement chaque sous-sélection avec $queryBuilder->execute()avant de l'utiliser $queryBuilder->getSQL(), tout fonctionnait. C'est comme si la connexion $queryBuilder->connectionrestait dans un état non valide pour créer un nouveau SQL avant d'exécuter le SQL actuellement préparé, malgré la nouvelle instance de QueryBuilder à chaque sous-sélection.

Ma solution était d'écrire les sous-sélections sans QueryBuilder.

Fabian Picone
la source
0

J'utilise ODBC, et ce correctif fonctionne pour moi: ODBC -> onglet DSN système -> double-cliquez pour configurer ma source de données -> détails -> onglet Curseurs -> Décochez [Ne pas mettre en cache les résultats des curseurs avant uniquement] - > cliquez sur Ok

Teemo
la source
0

Je rencontre souvent cette erreur et c'est toujours lorsque j'exécute une procédure stockée que j'ai débogué dans phpmyadmin ou SQL Workbench (je travaille en php en me connectant à mysqli).

L'erreur résulte du fait que le débogage implique l'insertion d'instructions SELECT à des points stratégiques du code pour me dire l'état des variables, etc. Erreur "Commandes désynchronisées" lorsqu'elles sont appelées depuis php. La solution est toujours de commenter ou de supprimer les sélections de débogage afin que la procédure n'ait qu'un seul jeu de résultats.

Nikkorian
la source
-1

Mon problème était que j'utilisais la première instruction prepare, puis j'utilisais la requête mysqli sur la même page et j'obtenais l'erreur "Commandes désynchronisées; vous ne pouvez pas exécuter cette commande maintenant". L'erreur était seulement alors quand j'utilisais le code qui avait la déclaration de préparation.

Ce que j'ai fait, c'est clore la question. et cela a fonctionné.

mysqli_stmt_close ($ stmt);

Mon code

get_category.php (ici en utilisant l'instruction prepare)

    <?php


    global $connection;
    $cat_to_delete =    mysqli_real_escape_string($connection, $_GET['get'] );

    $sql = "SELECT category_name FROM categories WHERE category_id = ? ;";


    $stmt = mysqli_stmt_init($connection);

    if (!mysqli_stmt_prepare($stmt, $sql))
        $_SESSION['error'] = "Error at preaparing for deleting query. mysqli_stmt_error($stmt) ." & redirect('../error.php');

    mysqli_stmt_bind_param($stmt, 's', $cat_to_delete);

    if (!mysqli_stmt_execute($stmt))
        $_SESSION['error'] = "ERror at executing delete category ".mysqli_stmt_error($stmt) &
            redirect('../error.php');


    mysqli_stmt_bind_result($stmt, $cat_name);

    if (!mysqli_stmt_fetch($stmt)) {
        mysqli_stmt_error($stmt);
    }



    mysqli_stmt_free_result($stmt);
    mysqli_stmt_close($stmt);

admin_get_category_body.php (ici mysqli)

        <?php

        if (isset($_GET['get']) && !empty($_GET['get']) )
        {
            include 'intodb/edit_category.php';
        }


        if (check_method('get') && isset($_GET['delete']) )
        {
            require 'intodb/delete_category.php';
        }


        if (check_method('get') && isset($_GET['get']) )
        {
            require 'intodb/get_category.php';
        }


        ?>

        <!--            start: cat body          -->

        <div     class="columns is-mobile is-centered is-vcentered">
            <div class="column is-half">
                <div   class="section has-background-white-ter box ">


                    <div class="has-text-centered column    " >
                        <h4 class="title is-4">Ctegories</h4>
                    </div>

                    <div class="column " >


                        <?php if (check_method('get') && isset($_GET['get'])) {?>
                        <form action="" method="post">
                            <?php } else {?>
                            <form action="intodb/add_category.php" method="post">
                                <?php } ?>

                                <label class="label" for="admin_add_category_bar">Add Category</label>
                                <div class="field is-grouped">

                                    <p class="control is-expanded">

                                        <?php if (check_method('get') && isset($_GET['get'])) {?>

                                            <input id="admin_add_category_bar" name="admin_add_category_bar_edit" class="input" type="text" placeholder="Add Your Category Here" value="<?php echo $cat_name; ?>">

                                            <?php


                                            ?>
                                        <?php } else {?>
                                            <input id="admin_add_category_bar" name="admin_add_category_bar" class="input" type="text" placeholder="Add Your Category Here">

                                        <?php } ?>
                                    </p>
                                    <p class="control">
                                        <input type="submit" name="admin_add_category_submit" class="button is-info my_fucking_hover_right_arrow" value="Add Category">
                                    </p>
                                </div>
                            </form>


                            <div class="">

                                <!--            start: body for all posts inside admin          -->


                                <table class="table is-bordered">
                                    <thead>
                                    <tr>
                                        <th><p>Category Name</p></th>
                                        <th><p>Edit</p></th>
                                        <th><p>Delete</p></th>
                                    </tr>
                                    </thead>

                                    <?php

                                    global $connection;
                                    $sql = "SELECT * FROM categories ;";

                                    $result = mysqli_query($connection, $sql);
                                    if (!$result) {
                                        echo mysqli_error($connection);
                                    }
                                    while($row = mysqli_fetch_assoc($result))
                                    {
                                        ?>
                                        <tbody>
                                        <tr>
                                            <td><p><?php echo $row['category_name']?></p></td>
                                            <td>
                                                <a href="admin_category.php?get=<?php echo $row['category_id']; ?>" class="button is-info my_fucking_hover_right_arrow" >Edit</a>

                                            </td>

                                            <td>
                                                <a href="admin_category.php?delete=<?php echo $row['category_id']; ?>" class="button is-danger my_fucking_hover_right_arrow" >Delete</a>

                                            </td>
                                        </tr>


                                        </tbody>
                                    <?php }?>
                                </table>

                                <!--           end: body for all posts inside admin             -->




                            </div>

                    </div>
                </div>


            </div>

        </div>
        </div>

Quelque chose qui vient de me traverser l'esprit, j'ajoute à nouveau une variable de connexion via global $ connection ;. Donc, je pense que fondamentalement, un tout nouvel ensemble de système de requête est démarré après la fin de l'instruction prepare avec mysqli_stmt_close ($ stmt); et aussi j'ajoute ces fichiers et d'autres choses via include

Mahad Ali
la source
get_category.php (ici en utilisant l'instruction prepare) pastebin.com/BiWysdYz admin_get_category_body.php (ici mysqli) pastebin.com/Pwm30icm Remarque: Impossible de publier tout le code en raison de limitations
Mahad Ali
Quelque chose qui vient de me traverser l'esprit, j'ajoute à nouveau une variable de connexion via global $ connection ;. Donc, je pense que fondamentalement, un tout nouvel ensemble de système de requête est démarré après la fin de l'instruction prepare avec mysqli_stmt_close ($ stmt); et aussi j'ajoute ces fichiers et d'autres choses via include.
Mahad Ali
-1

C'est une vieille question, mais aucune des réponses publiées n'a fonctionné dans mon cas, j'ai trouvé que dans mon cas, j'avais des sélections et des mises à jour sur une table dans ma procédure stockée, la même table avait un déclencheur de mise à jour qui était déclenché et déclenché le procédure dans une boucle infinie. Une fois le bogue trouvé, l'erreur a disparu.

Shelbypereira
la source