Comandos desincronizados; no puedes ejecutar este comando ahora

93

Estoy intentando ejecutar mi código PHP, que llama a dos consultas MySQL a través de mysqli, y aparece el error "Comandos desincronizados; no puede ejecutar este comando ahora".

Aquí está el código que estoy usando

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

He intentado leer sobre esto, pero no estoy seguro de qué hacer. He leído sobre el resultado de la tienda y el resultado gratuito, sin embargo, estos no han hecho ninguna diferencia al usarlos. No estoy seguro de exactamente en qué punto se está causando este error y me gustaría saber por qué se está causando y cómo solucionarlo.

Siguiendo mis declaraciones de depuración, el primer bucle if para countQuery ni siquiera se ingresa, debido a un error en mi sintaxis sql cerca '% ? %'. Sin embargo, si solo selecciono en *lugar de intentar limitar en función de una cláusula LIKE, todavía obtengo el error de sincronización del comando.

Joshxtothe4
fuente

Respuestas:

114

No puede tener dos consultas simultáneas porque mysqli usa consultas sin búfer de forma predeterminada (para declaraciones preparadas; es lo contrario para vainilla mysql_query). Puede obtener el primero en una matriz y recorrerlo, o decirle a mysqli que almacene las consultas (usando $stmt->store_result()).

Consulte aquí para obtener más detalles.

HoLyVieR
fuente
3
Estoy de acuerdo, mysqli tiene un poco de daño cerebral. Sin embargo , hace lo correcto con el controlador PDO mysql.
17
Usted puede tener dos consultas simultáneas - sólo tiene que ejecutar $stmt->store_result();Creo que su respuesta debe hacer más que clara.
Shadow
3
Me tomó años encontrar esta información, en ningún lugar se muestra fácilmente. Gracias. Solo separo mis consultas $select_stmt->close();para dividirlas (no simultáneas sino de procedimiento
n34_panda
@flussence, Usted declaró que "mysqli usa consultas sin búfer de forma predeterminada". Entonces, ¿cómo podemos configurarlo para que haga lo contrario?
Pacerier
1
Sé que parece extraño, pero tuve este error al ejecutar una consulta con mysqli_query violando una clave externa ... así que si esto le sucede a alguien, verifique que su consulta INSERT no esté violando ninguna clave externa
lucaferrario
34

Resolví este problema en mi aplicación C; así es como lo hice:

  1. Citando de foros de mysql:

    Este error se produce cuando finaliza su consulta con un delimitador de punto y coma dentro de la aplicación . Si bien es necesario terminar una consulta con un delimitador de punto y coma al ejecutarla desde la línea de comandos o en el navegador de consultas, elimine el delimitador de la consulta dentro de su aplicación.

  2. Después de ejecutar mi consulta y tratar con los resultados [API C: mysql_store_result()], iteraré sobre cualquier resultado potencialmente pendiente adicional que ocurra a través de la ejecución de múltiples sentencias SQL, como dos o más sentencias select (una tras otra sin ocuparse de los resultados).

    El hecho es que mis procedimientos no devuelven múltiples resultados, pero la base de datos no lo sabe hasta que ejecuto: [C API: mysql_next_result()]. Hago esto en un bucle (por si acaso) hasta que devuelve un valor distinto de cero. Ahí es cuando el controlador de conexión actual sabe que está bien ejecutar otra consulta (guardo en caché mis controladores para minimizar la sobrecarga de conexión).

    Este es el bucle que uso:

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

No conozco PHP pero estoy seguro de que tiene algo similar.

tracy.brown
fuente
11
Esto fue todo para mí. En PHP acabo de agregar: while (mysqli_next_result ($ con));
Josh
Gracias por la respuesta que resolvió mi problema. Quité el delimitador y funciona. No liberé (obtuve) ni almacené mis resultados, pero cerré el cursor y reconstruí una vez que terminé una declaración de consulta.
Chen Xie
@Josh, ¿cómo hacer eso en la mysqlextensión heredada ?
Pacerier
1
Al eliminar el punto y coma al final de la consulta, se solucionó el problema "Comandos no sincronizados; no se puede ejecutar este comando ahora" al usar Python MySQLdb.
Genoma
17

Hoy tuve el mismo problema, pero solo cuando trabajaba con un procedimiento almacenado. Esto hace que la consulta se comporte como una consulta múltiple, por lo que debe "consumir" otros resultados disponibles antes de realizar otra consulta.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
stalin beltran
fuente
Este es un punto importante: los procedimientos almacenados devuelven un conjunto de resultados por encima de cualquier conjunto de resultados que el código en el SP pueda generar. Tienes que manejar eso o recibir este error: stackoverflow.com/a/2315229/4495850
Richard
11

Llamo a esta función cada vez antes de usar $ mysqli-> query Funciona con procedimientos almacenados también.

function clearStoredResults(){
    global $mysqli;

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

}
Juergen
fuente
5

Una vez que usaste

stmt->execute();

Usted PUEDE cerrarla utilizar otra consulta.

stmt->close();

Este problema me persiguió durante horas. Con suerte, arreglará el tuyo.

Carl James
fuente
1
No es necesario cerrar la declaración. Como @stalinbeltran respondió anteriormente, necesitamos "consumir" el resultado de una declaración antes de preparar otra. Entonces, $stmt1->execute(); $stmt2=$conn->prepare(...)daría este error, pero $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)funcionaría bien.
Jay Dadhania
Hermano me ayudó gracias. Para todos los que dicen esto y aquello, usé mysqli_prepare dos veces antes de cerrar la primera. Funciona.
Abhinash Majhi
2

Yo uso CodeIgniter. Un servidor bien ... este probablemente más antiguo ... De todos modos usando

$this->db->reconnect();

Arreglado.

Normando
fuente
7
¿Cómo aborda esto el problema?
Jeremy J Starcher
4
@Norman, esto no "soluciona" el problema. Es mera evita It de tirar toda la conexión y volver a conectar de nuevo. Esto no tiene ningún sentido desde el punto de vista del rendimiento.
Pacerier
1

El problema es la biblioteca C del cliente MySQL, en la que se basan la mayoría de las API de MySQL. El problema es que la biblioteca C no admite la ejecución simultánea de consultas, por lo que todas las API construidas sobre eso tampoco lo hacen. Incluso si usa consultas sin búfer. Esta es una de las razones por las que se escribió la API MySQL asincrónica. Se comunica directamente con el servidor MySQL usando TCP y el alambre-protocolo no apoyar consultas simultáneas.

Su solución es modificar el algoritmo para que no necesite tener ambos en progreso a la vez, o cambiarlos para usar consultas en búfer, que es probablemente una de las razones originales de su existencia en la biblioteca C (la otra es proporcionar una especie de cursor).

estático
fuente
1
No necesito tener ambos en progreso a la vez, estoy feliz de que countQuery termine completamente antes de mi segunda consulta, pero no estoy seguro de cómo evitar que countQuery esté en progreso
No está recuperando ningún dato de countQuery, es por eso que todavía está 'en progreso'. Recupere todas las filas o cámbielo a SELECT COUNT (ARTICLE_NO) y obtenga esa fila. Entonces se ejecutará su segunda consulta.
staticsan
Cuando dice "la API MySQL asincrónica", ¿a qué API se refiere? Además, no obtengo tu conclusión. Este "problema" se puede solucionar sin necesidad de que la API sea asincrónica.
Pacerier
1
Para ser honesto, @Pacerier, ¡tampoco estoy seguro de lo que quise decir! Han sucedido muchas cosas en seis años en la conectividad MySQL, por lo que todo lo que pensé que me refería probablemente haya sido renombrado y / o incorporado en algún otro controlador nuevo.
staticsan
1

para resolver este problema, debe almacenar los datos de los resultados antes de usarlos

$numRecords->execute();

$numRecords->store_result();

eso es todo

Nader Ben Mabrouk
fuente
1

Otra causa: store_result () no se puede llamar dos veces.

Por ejemplo, en el siguiente código, se imprime el Error 5.

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

(Es posible que esto no sea relevante para el código de muestra original, pero puede ser relevante para las personas que buscan respuestas a este error).

David G.
fuente
1

Aquí está lo que era MI PROBLEMA !!!

El enlace de parámetros era "dinámico", así que tenía una variable que establece los parámetros de los datos para usar bind_param . Entonces esa variable estaba mal, pero en lugar de arrojar un error como "datos de parámetros incorrectos", dice "fuera de sincronización bla bla bla", así que estaba confundido ...

Ari Waisberg
fuente
0

Creo que el problema es que estás haciendo una nueva conexión en la función y luego no la cierras al final. ¿Por qué no intentas pasar la conexión existente y reutilizarla?

Otra posibilidad es que regrese de la mitad de una búsqueda de bucle while. Nunca completas esa búsqueda externa.

Paul Tomblin
fuente
1
Si hago $ con global (lo cual es una mala práctica, pero debería funcionar como lo describe), todavía tengo el mismo error.
1
No creo que tener una conexión global sea una mala práctica
Mathieu J.
0

Compruebe si está escribiendo todos los parámetros correctamente. Lanza el mismo error si la cantidad de parámetros definidos y luego pasados ​​a la función son diferentes.

Mixtelf
fuente
0

Esto no está relacionado con la pregunta original, pero tuve el mismo mensaje de error y este hilo es el primer resultado en Google y me tomó un tiempo descubrir cuál era el problema, por lo que puede ser útil para otros:

NO estoy usando mysqli, sigo usando mysql_connect. Tenía algunas consultas simples, pero UNA consulta hizo que todas las demás consultas fallaran dentro de la misma conexión.

Yo uso mysql 5.7 y php 5.6. Tenía una tabla con el tipo de datos "JSON". obviamente, mi versión de php no reconoció el valor de retorno de mysql (php simplemente no sabía qué hacer con el formato JSON porque el módulo mysql incorporado era demasiado antiguo (al menos creo))

por ahora cambié JSON-Field-Type a Text (ya que por ahora no necesito la funcionalidad JSON nativa de mysql) y todo funciona bien

mech
fuente
0

Si usa el conjunto de resultados con búfer o sin búfer para obtener datos, primero debe simplemente borrar los datos recuperados de la memoria, una vez que haya obtenido todos los datos . Como no puede ejecutar otro procedimiento MYSQL en la misma conexión hasta que borre la memoria recuperada. Agregue esta función a continuación en el extremo derecho de su secuencia de comandos, por lo que resolverá el problema

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

Referencia de la documentación de PHP

Kaz
fuente
1
Si no necesita algunos registros, entonces no debería haberlos seleccionado en primer lugar. En lugar de simplemente liberarlos, simplemente no los seleccione en absoluto. Y si no es el caso y usted obtuvo todos los registros seleccionados, entonces no habrá ningún error de este tipo en absoluto, tampoco es necesario llamar a close () o free (). A partir de los procedimientos almacenados, hay un método menos bárbaro, descrito en las respuestas anteriores
Your Common Sense
0

Me encontré con este error usando Doctrine DBAL QueryBuilder.

Creé una consulta con QueryBuilder que usa subselecciones de columna, también creada con QueryBuilder. Las subselecciones solo se crearon mediante $queryBuilder->getSQL()y no se ejecutaron. El error ocurrió al crear la segunda subselección. Al ejecutar provisionalmente cada subselección con $queryBuilder->execute()antes de usar $queryBuilder->getSQL(), todo funcionó. Es como si la conexión $queryBuilder->connectionpermaneciera en un estado no válido para crear un nuevo SQL antes de ejecutar el SQL actualmente preparado, a pesar de la nueva instancia de QueryBuilder en cada subselección.

Mi solución fue escribir las subselecciones sin QueryBuilder.

Fabián Picone
fuente
0

Estoy usando ODBC, y esta solución me funciona: ODBC -> pestaña System DSN -> doble clic para configurar mi fuente de datos -> detalles -> pestaña Cursores -> Desmarque [No almacenar en caché los resultados de los cursores de solo avance] - > haga clic en Aceptar

Teemo
fuente
0

A menudo encuentro este error y es siempre cuando ejecuto un procedimiento almacenado que he estado depurando en phpmyadmin o SQL Workbench (estoy trabajando en php conectándome con mysqli).

El error se debe al hecho de que la depuración implica insertar sentencias SELECT en puntos estratégicos del código para indicarme el estado de las variables, etc. Ejecutar un procedimiento almacenado que produce múltiples conjuntos de resultados en estos entornos de cliente está bien, pero produce el " Comandos no sincronizados "error cuando se llama desde php. La solución es siempre comentar o eliminar las selecciones de depuración para que el procedimiento tenga solo un conjunto de resultados.

Nikkorian
fuente
-1

Mi problema era que estaba usando la primera declaración de preparación y luego estaba usando la consulta mysqli en la misma página y recibía el error "Comandos no sincronizados; no puede ejecutar este comando ahora". El error fue solo entonces cuando estaba usando el código que tenía la declaración de preparación.

Lo que hice fue cerrar la pregunta. Y funcionó.

mysqli_stmt_close ($ stmt);

Mi código

get_category.php (aquí usando la declaración de preparación)

    <?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 (aquí 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>

Algo que acaba de pasar por mi mente, también estoy agregando nuevamente la variable de conexión a través de $ conexión global ;. Así que creo que básicamente se está iniciando un nuevo conjunto de sistema de consultas después de finalizar la declaración de preparación con mysqli_stmt_close ($ stmt); y también estoy agregando estos archivos y otras cosas a través de include

Mahad Ali
fuente
get_category.php (aquí usando la declaración de preparación) pastebin.com/BiWysdYz admin_get_category_body.php (aquí mysqli) pastebin.com/Pwm30icm Nota: No se puede publicar todo el código debido a una limitación
Mahad Ali
Algo que acaba de pasar por mi mente, también estoy agregando nuevamente la variable de conexión a través de $ conexión global ;. Así que creo que básicamente se está iniciando un nuevo conjunto de sistema de consultas después de finalizar la declaración de preparación con mysqli_stmt_close ($ stmt); y también estoy agregando estos archivos y otras cosas a través de include.
Mahad Ali
-1

Esta es una pregunta antigua, pero ninguna de las respuestas publicadas funcionó en mi caso, descubrí que en mi caso tenía selecciones y actualizaciones en una tabla en mi procedimiento almacenado, la misma tabla tenía un disparador de actualización que se estaba activando y enviando el procedimiento en un bucle infinito. Una vez que se encontró el error, el error desapareció.

shelbypereira
fuente