web-dev-qa-db-de.com

Befehle nicht synchron; Sie können diesen Befehl jetzt nicht ausführen

Ich versuche, meinen PHP Code auszuführen, der zwei MySQL-Abfragen über mysqli aufruft, und erhalte die Fehlermeldung "Befehle nicht synchronisiert; Sie können diesen Befehl jetzt nicht ausführen".

Hier ist der Code, den ich verwende

<?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;
        }
    }
}

Ich habe versucht, dies nachzulesen, bin mir aber nicht sicher, was ich tun soll. Ich habe über das Speicherergebnis und das freie Ergebnis gelesen, aber diese haben keinen Unterschied gemacht, wenn sie verwendet werden. Ich bin nicht sicher, an welcher Stelle genau dieser Fehler verursacht wird, und möchte wissen, warum er verursacht wird und wie er behoben werden kann.

Nach meinen Debug-Anweisungen wird die erste if-Schleife für countQuery aufgrund eines Fehlers in meiner SQL-Syntax in der Nähe von '% ? %' Nicht einmal eingegeben. Wenn ich jedoch nur * Auswähle, anstatt zu versuchen, auf der Grundlage einer LIKE-Klausel eine Beschränkung vorzunehmen, wird der Befehl trotzdem nicht mehr synchronisiert.

84
Joshxtothe4

Sie können nicht zwei Abfragen gleichzeitig haben, da mysqli standardmäßig ungepufferte Abfragen verwendet (für vorbereitete Anweisungen; für Vanilla ist es das Gegenteil mysql_query). Sie können entweder den ersten in ein Array holen und diesen durchlaufen oder mysqli anweisen, die Abfragen zu puffern (mit $stmt->store_result() ).

Siehe hier für Details.

104
user42092

Ich habe dieses Problem in meiner C-Anwendung gelöst - so habe ich es gemacht:

  1. Zitat aus MySQL-Foren:

    Dieser Fehler tritt auf, wenn Sie Ihre Abfrage mit einem Semikolon-Trennzeichen in der Anwendung beenden. Während es erforderlich ist, eine Abfrage mit einem Semikolontrennzeichen zu beenden, wenn Sie sie über die Befehlszeile oder im Abfragebrowser ausführen, entfernen Sie das Trennzeichen aus der Abfrage in Ihrer Anwendung.

  2. Nachdem ich meine Abfrage ausgeführt und die Ergebnisse [C API: mysql_store_result()] verarbeitet habe, durchlaufe ich alle weiteren potenziell ausstehenden Ergebnisse, die über die Ausführung mehrerer SQL-Anweisungen wie zwei oder mehr select-Anweisungen (Back-to-Back, ohne zu handeln) auftreten mit den Ergebnissen).

    Tatsache ist, dass meine Prozeduren nicht mehrere Ergebnisse zurückgeben, aber die Datenbank weiß das erst, wenn ich Folgendes ausführe: [C API: mysql_next_result()]. Ich mache dies in einer Schleife (aus gutem Grund), bis es ungleich Null zurückgibt. In diesem Fall weiß der aktuelle Verbindungshandler, dass es in Ordnung ist, eine weitere Abfrage auszuführen (ich habe meine Handler zwischengespeichert, um den Verbindungsaufwand zu minimieren).

    Dies ist die Schleife, die ich benutze:

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

Ich weiß es nicht PHP aber ich bin sicher, es hat etwas ähnliches.

31
tracy.brown

Ich hatte heute das gleiche Problem, aber nur bei der Arbeit mit einer gespeicherten Prozedur. Dadurch verhält sich die Abfrage wie eine Mehrfachabfrage, sodass Sie andere verfügbare Ergebnisse "verbrauchen" müssen, bevor Sie eine weitere Abfrage erstellen.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
15
stalin beltran

Ich rufe diese Funktion jedes Mal auf, bevor ich $ mysqli-> query verwende. Funktioniert auch mit gespeicherten Prozeduren.

function clearStoredResults(){
    global $mysqli;

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

}
7
Juergen

Ich benutze CodeIgniter. Ein Server OK ... dieser wahrscheinlich älter ... Wie auch immer mit

$this->db->reconnect();

Behoben.

2
Norman

Einmal benutzt

stmt->execute();

Sie müssen es schließen, um eine andere Abfrage zu verwenden.

stmt->close();

Dieses Problem hat mich stundenlang gejagt. Hoffentlich wird es dein Problem beheben.

2
Carl James

Für diejenigen, die die vorherigen Antworten nicht geholfen haben ... hier ist, was MEIN PROBLEM war !!!

die Param-Bindung war "dynamisch", also hatte ich eine Variable, die die Parameter der Daten festlegt, um bind_param zu verwenden. Diese Variable war also falsch, aber anstatt einen Fehler wie "Falsche Parameterdaten" auszulösen, heißt es "Nicht synchronisiert, bla, bla, bla", also war ich verwirrt ...

Ich hoffe es hat jemandem geholfen!

1
Ari Waisberg

Das Problem ist die MySQL-Client-C-Bibliothek, auf der die meisten MySQL-APIs aufbauen. Das Problem ist, dass die C-Bibliothek die gleichzeitige Ausführung von Abfragen nicht unterstützt, sodass dies auch für alle darauf aufbauenden APIs nicht möglich ist. Auch wenn Sie ungepufferte Abfragen verwenden. Dies ist ein Grund, warum die asynchrone MySQL-API geschrieben wurde. Es kommuniziert direkt mit dem MySQL-Server über TCP und das Wire-Protokoll funktioniert unterstützt gleichzeitige Abfragen.

Ihre Lösung besteht darin, entweder den Algorithmus so zu ändern, dass nicht beide gleichzeitig ausgeführt werden müssen, oder sie so zu ändern, dass gepufferte Abfragen verwendet werden. Dies ist wahrscheinlich einer der ursprünglichen Gründe für ihre Existenz in der C - Bibliothek (der andere ist, eine Art Cursor bereitstellen).

1
staticsan

um dieses Problem zu lösen, müssen Sie die Ergebnisdaten speichern, bevor Sie sie verwenden können

$numRecords->execute();

$numRecords->store_result();

das ist alles

1

Ich denke, das Problem ist, dass Sie eine neue Verbindung in der Funktion herstellen und sie dann am Ende nicht schließen. Warum versuchen Sie nicht, die vorhandene Verbindung weiterzugeben und erneut zu verwenden?

Eine andere Möglichkeit besteht darin, dass Sie aus der Mitte eines Holens einer while-Schleife zurückkehren. Sie schließen diesen äußeren Abruf nie ab.

0
Paul Tomblin

Dies hat nichts mit der ursprünglichen Frage zu tun, aber ich hatte die gleiche Fehlermeldung und dieser Thread ist der erste Treffer in Google. Es dauerte eine Weile, bis ich herausgefunden hatte, was das Problem war, sodass es für andere von Nutzen sein könnte:

ich benutze kein MySQL, benutze aber immer noch MySQL_Connect. Ich hatte einige einfache Abfragen, aber EINE Abfrage führte dazu, dass alle anderen Abfragen innerhalb derselben Verbindung fehlschlugen.

Ich benutze MySQL 5.7 und PHP 5.6. Ich hatte eine Tabelle mit dem Datentyp "JSON". Offensichtlich hat meine PHP-Version den Rückgabewert von MySQL nicht erkannt (PHP wusste einfach nicht, was mit dem JSON-Format zu tun ist, weil das eingebaute MySQL-Modul zu alt war (zumindest denke ich)).

im Moment habe ich den JSON-Feld-Typ in Text geändert (da ich die native mysql JSON-Funktionalität nicht benötige) und alles funktioniert einwandfrei

0
mech

Wenn Sie die Ergebnismenge "Gepuffert" oder "Ungepuffert" zum Abrufen von Daten verwenden, müssen Sie zunächst die abgerufenen Daten aus dem Speicher löschen. Nachdem Sie alle Daten abgerufen haben. Da Sie keine andere MYSQL-Prozedur auf derselben Verbindung ausführen können, bis Sie den abgerufenen Speicher gelöscht haben. Fügen Sie diese Funktion unten rechts in Ihr Skript ein, damit das Problem behoben wird

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

Verweis aus der PHP Dokumentation

0
Kaz

Überprüfen Sie, ob Sie alle Parameter richtig eingeben. Es wird der gleiche Fehler ausgegeben, wenn die Anzahl der definierten und dann an die Funktion übergebenen Parameter unterschiedlich ist.

0
Mixtelf

Ich bin mit Doctrine DBAL QueryBuilder auf diesen Fehler gestoßen.

Ich habe mit QueryBuilder eine Abfrage erstellt, die Spalten-Unterauswahlen verwendet, die ebenfalls mit QueryBuilder erstellt wurden. Die Unterauswahlen wurden nur über $queryBuilder->getSQL() erstellt und nicht ausgeführt. Der Fehler ist beim Erstellen der zweiten Unterauswahl aufgetreten. Indem Sie jede Unterauswahl vorläufig mit $queryBuilder->execute() ausführen, bevor Sie $queryBuilder->getSQL() verwenden, hat alles funktioniert. Es ist, als ob die Verbindung $queryBuilder->connection bleibt trotz der neuen QueryBuilder-Instanz in jeder Unterauswahl in einem ungültigen Zustand, um eine neue SQL zu erstellen, bevor die aktuell vorbereitete SQL ausgeführt wird.

Meine Lösung bestand darin, die Unterauswahlen ohne QueryBuilder zu schreiben.

0
Fabian Picone