125

I am trying to execute my PHP code, which calls two MySQL queries via mysqli, and get the error "Commands out of sync; you can't run this command now".

Here is the code I am using

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

I have tried reading up on this, but I am unsure of what to do. I have read about store result and free result, however these have made no difference when using them. I am unsure at exactly which point this error is being caused, and would like to know why it is being caused, and how to fix it.

Going by my debug statements, the first if loop for countQuery is not even being entered, because of an error in my sql syntax near near '% ? %'. However if I just select * instead of trying to limit based on a LIKE clause, I still get the command out of sync error.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Joshxtothe4
  • 4,061
  • 10
  • 53
  • 83

24 Answers24

134

You can't have two simultaneous queries because mysqli uses unbuffered queries by default (for prepared statements; it's the opposite for vanilla mysql_query). You can either fetch the first one into an array and loop through that, or tell mysqli to buffer the queries (using $stmt->store_result()).

See here for details.

HoLyVieR
  • 10,985
  • 5
  • 42
  • 67
  • 4
    I agree, mysqli is a bit brain-damaged. It _does_ do the right thing with the PDO mysql driver though. –  Mar 05 '09 at 13:59
  • 20
    You *can* have two simultaneous queries - you just need to run `$stmt->store_result();` I think your response should make that more clear. – Shadow Mar 14 '13 at 07:24
  • 4
    Taking me ages to find this information out - no where is it easily displayed. Thanks. I just seperate my queries with `$select_stmt->close();` to split them (not simultaneous but procedural – n34_panda Jun 07 '14 at 11:13
  • @flussence, You stated that "mysqli uses unbuffered queries by default". So how can we set it to do otherwise? – Pacerier Jun 29 '15 at 08:34
  • 1
    You can create 2 simultaneous connections, and an unbuffered prepared statement on each without getting the sync error. – alfadog67 Dec 06 '16 at 21:50
  • How to resolve the same issue in wordpress with `wpdb` for calling stored procedure and this error comes "Commands out of sync; you can't run this command now" – Muhammad Muazzam Nov 18 '17 at 13:06
  • 1
    I know that it seems weird, but I had this error while executing a query with mysqli_query violating a foreign key...so if this happens to anyone, double check that your INSERT query is not violating any foreign key – lucaferrario Jan 29 '18 at 09:35
  • are you sure it is unbuffered by default. is there a config file for this – Gavindra Kalikapersaud Jun 15 '18 at 02:11
42

I solved this problem in my C application - here's how I did it:

  1. Quoting from mysql forums:

    This error results when you terminate your query with a semicolon delimiter inside the application. While it is required to terminate a query with a semicolon delimiter when executing it from the command line or in the query browser, remove the delimiter from the query inside your application.

  2. After running my query and dealing with the results [C API: mysql_store_result()], I iterate over any further potentially pending results that occurs via multiple SQL statement execution such as two or more select statements (back to back without dealing with the results).

    The fact is that my procedures don't return multiple results but the database doesn't know that until I execute: [C API: mysql_next_result()]. I do this in a loop (for good measure) until it returns non-zero. That's when the current connection handler knows it's okay to execute another query (I cache my handlers to minimize connection overhead).

    This is the loop I use:

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

I don't know PHP but I'm sure it has something similar.

tracy.brown
  • 589
  • 4
  • 9
  • 13
    This was it for me. In PHP I just added:while(mysqli_next_result($con)); – Josh Apr 24 '12 at 00:02
  • Thanks for the answer that solved my problem. I removed the delimiter and it works. I didn't free(fetch) or store my results, but close cursor and re-build once I finished one statement of query. – Chen Xie Oct 12 '12 at 23:19
  • @Josh, How to do that in legacy `mysql` extension? – Pacerier Apr 20 '15 at 11:26
  • 1
    Removing the semicolon at the end of the query fixed the "Commands out of sync; you can't run this command now" issue when using Python MySQLdb. – Genome Feb 16 '18 at 03:48
19

I had today the same problem, but only when working with a stored procedure. This make the query behave like a multi query, so you need to "consume" other results available before make another query.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
stalin beltran
  • 191
  • 1
  • 3
  • This is a significant point: stored procedures return a result set over and above any result set the code in the SP might generate. You have to handle that or get this error: http://stackoverflow.com/a/2315229/4495850 – Richard Jun 26 '16 at 16:53
19

I call this function every time before using $mysqli->query, and it works with stored procedures as well.

function clearStoredResults(){
    global $mysqli;
    
    do {
         if ($res = $mysqli->store_result()) {
           $res->free();
         }
    } while ($mysqli->more_results() && $mysqli->next_result());        
    
}
T.Todua
  • 53,146
  • 19
  • 236
  • 237
Juergen Schulze
  • 1,515
  • 21
  • 29
10

Once you used

stmt->execute();

You MAY close it to use another query.

stmt->close();

This problem was hunting me for hours. Hopefully, it will fix yours.

ice
  • 141
  • 2
  • 12
  • 2
    Closing the statement is not necessary. As @stalinbeltran answered above, we need to "consume" the result of a statement before preparing another. So, `$stmt1->execute(); $stmt2=$conn->prepare(...)` would give this error, but `$stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)` would work just fine. – Jay Dadhania Oct 10 '19 at 13:20
  • 1
    Bro it helped me thank you. f everyone who says this and that , I used mysqli_prepare two times before closing the first one. It works. – Abhinash Majhi Aug 20 '20 at 03:23
3

I use CodeIgniter. One server OK ... this one probably older ... Anyway using

$this->db->reconnect();

Fixed it.

j0k
  • 22,600
  • 28
  • 79
  • 90
Norman
  • 97
  • 1
  • 1
3

to solve this problem you have to store result data before use it

$numRecords->execute();

$numRecords->store_result();

that's all

Lucas Zamboulis
  • 2,494
  • 5
  • 24
  • 27
1

Here is what was MY PROBLEM!!!

The param binding was "dynamic" so I had a variable that sets the params of the data in order to use bind_param. So that variable was wrong but instead of throwing an error like "wrong param data" it says "out of sync bla bla bla" so I was confused...

Dharman
  • 30,962
  • 25
  • 85
  • 135
Ari Waisberg
  • 1,186
  • 1
  • 12
  • 23
1

Another cause: store_result() cannot be called twice.

For instance, in the following code, Error 5 is printed.

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

(This may not be relevant to the original sample code, but it can be relevant to people seeking answers to this error.)

David G.
  • 595
  • 1
  • 4
  • 11
1

The problem is the MySQL client C library, which most MySQL APIs are built on. The problem is that the C library doesn't support simultaneous execution of queries, so all APIs built on top of that also do not. Even if you use unbuffered queries. This is one reason why the asynchronous MySQL API was written. It communicates directly with the MySQL server using TCP and the wire-protocol does support simultaneous queries.

Your solution is to either modify the algorithm so you don't need to have both in progress at once, or change them to use buffered queries, which is probably one of the original reasons for their existence in the C library (the other is to provide a kind of cursor).

staticsan
  • 29,935
  • 4
  • 60
  • 73
  • 1
    I don't need to have both in progress at once, I am happy for countQuery to finish completely before my second query, but I am unsure how to stop countQuery from being in proggress –  Mar 06 '09 at 09:24
  • You're not retrieving any data from countQuery, that's why it's still 'in progress'. Either retrieve all the rows, or change it to SELECT COUNT(ARTICLE_NO) and get that row. Then your second query will run. – staticsan Mar 08 '09 at 21:45
  • When you say "the asynchronous MySQL API", which API are you referring to? Also, I'm not getting your conclusion. This "problem" can be fixed without needing the API to be asynchronous. – Pacerier Jun 30 '15 at 04:21
  • 1
    To be honest @Pacerier I'm not sure anymore quite what I meant, either! A lot has happened in six years in MySQL connectivity so whatever I thought I was referring to has probably been renamed and/or incorporated in some other new driver. – staticsan Jun 30 '15 at 07:44
1

Just for reference i had this problem mixing both multi_query and query in the same code:

$connection->multi_query($query);
...
$connection->query($otherQuery);

Which for what i read had unconsumed results pending, therefore causing in the mentioned error.

I solved it with a loop consuming all the results of the multi_query:

$connection->multi_query($query);
while ($connection->next_result()); // <--- solves the problem
...
$connection->query($otherQuery);

In my case all the queries in the multi_query where inserts so i had no interest in the results themselves.

Isac
  • 1,834
  • 3
  • 17
  • 24
0

Check to see if you are typing all the parameters correctly. It throws the same error if the amount of parameters defined and then passed to the function are different.

Mixtelf
  • 13
  • 2
0

This is not related to the original question, but i had the same error-message and this thread is the first hit in Google and it took me a while to figure out what the Problem was, so it May be of use for others:

i'm NOT using mysqli, still using mysql_connect i had some simple querys, but ONE query caused all other querys to fail within the same Connection.

I use mysql 5.7 and php 5.6 i had a table with the data-Type "JSON". obviously, my php-version did not recognize the return value from mysql (php just did not know what to do with the JSON-Format because the built-in mysql-module was too old (at least i think))

for now i changed the JSON-Field-Type to Text (as for now i don't need the native mysql JSON-functionality) and everything works fine

mech
  • 617
  • 6
  • 16
0

To clear the referencing memory, and run the next MYSQL fetch

If you either use Buffered or Unbuffered result set for fetching data, first you must simply clear the fetched data from the memory, once you have fetched all the data. As you can't execute another MYSQL procedure on the same connection until you clear the fetched memory.

Add this below function right end of your script, so it will solve the problem

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

Reference from the PHP documentation

Kazmi
  • 1,198
  • 9
  • 20
  • 1
    If you don't need some records, then **you shouldn't have selected them in the first place.** Instead of just freeing them out simply don't select them at all. And if it is not the case and you fetched all the records selected, then there will be no such error at all as well there is no need for calling close() or free(). As of the stored procedures, there is a less barbaric method, described in the answers above – Your Common Sense Mar 05 '18 at 08:26
  • @Kaz I don't see anything on that manual that recommends `method(); or method()`. – mickmackusa Feb 07 '21 at 10:34
0

I ran into this error using Doctrine DBAL QueryBuilder.

I created a query with QueryBuilder that uses column subselects, also created with QueryBuilder. The subselects were only created via $queryBuilder->getSQL() and not executed. The error happened on creating the second subselect. By provisionally executing each subselect with $queryBuilder->execute() before using $queryBuilder->getSQL(), everything worked. It is as if the connection $queryBuilder->connection remains in an invalid state for creating a new SQL before executing the currently prepared SQL, despite the new QueryBuilder instance on each subselect.

My solution was to write the subselects without QueryBuilder.

fabpico
  • 2,628
  • 4
  • 26
  • 43
0

I am using ODBC, and this fix works for me: ODBC -> tab System DSN -> double click to configure my data source -> details -> tab Cursors -> Uncheck [Don't cache results of forward-only cursors] -> click Ok

Teemo
  • 211
  • 2
  • 6
0

I think the problem is that you're making a new connection in the function, and then not closing it at the end. Why don't you try passing in the existing connection and re-using it?

Another possibility is that you're returning out of the middle of a while loop fetching. You never complete that outer fetch.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
0

I often hit this error and it's always when I run a stored procedure that I have been debugging in phpmyadmin or SQL Workbench (I am working in php connecting with mysqli).

The error results from the fact that the debugging involves inserting SELECT statements at strategic points in the code to tell me the state of variables, etc. Running a stored procedure that produces multiple results sets in these client environments is fine, but it produces the "Commands out of sync" error when called from php. The solution is always to comment-out or remove the debugging selects so the procedure has only one result set.

Nikkorian
  • 770
  • 4
  • 10
0

I put this line of code after I was done collecting the results of the first query. Worked for me

mysqli_next_result($connection);
Willt42
  • 125
  • 2
  • 10
-1

My problem was that I was using first prepare statement and then I was using mysqli query on the same page and was getting the error "Commands out of sync; you can't run this command now". The error was only then when I was using the code that had prepare statement.

What I did was to close the question. and it worked.

mysqli_stmt_close($stmt);

My code

get_category.php (here using prepare statement )

    <?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 (here 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>

Something that just crossed my mind, I am also again adding connection variable via global $connection;. So I think basically a whole new set of query system is being started after ending of prepare statement with mysqli_stmt_close($stmt); and also I am adding these files and other stuff via include

Mahad Ali
  • 69
  • 1
  • 8
  • get_category.php (here using prepare statement ) https://pastebin.com/BiWysdYz admin_get_category_body.php (here mysqli) https://pastebin.com/Pwm30icm Note: Can't post all the code due to limitation – Mahad Ali May 04 '19 at 15:10
  • Something that just crossed my mind, I am also again adding connection variable via global $connection;. So I think basically a whole new set of query system is being started after ending of prepare statement with mysqli_stmt_close($stmt); and also I am adding these files and other stuff via include. – Mahad Ali May 04 '19 at 15:25
-1

This is an old question, but none of the posted answers worked in my case, I found that in my case I had selects and updates on a table in my stored procedure, the same table had an update trigger which was being triggered and senging the procedure into an infinite loop. Once the bug was found the error went away.

shelbypereira
  • 2,097
  • 3
  • 27
  • 50
-1
<?php
$getData = $db->query("CALL `pet_sitter_list`()");
while ($row = mysqli_fetch_object($getData)): ?>
 your data fetching ...
<?php endwhile; 
$getData->close();
$db->next_result();
?>

like this way you can call another query after with no problem.

  • Please don't add answers that plagiarize other answers – Your Common Sense Jul 29 '23 at 21:05
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 04 '23 at 06:50
-2

The definitive solution for this error is the following:

1) You must copy and paste this code above the next query to the stored procedure.

do if($result=mysqli_store_result($myconnection)){ mysqli_free_result($result); } while(mysqli_more_results($myconnection) && mysqli_next_result($myconnection));

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 21 '21 at 23:11
-3

Create two connections, use both separately

$mysqli = new mysqli("localhost", "Admin", "dilhdk", "SMS");

$conn = new mysqli("localhost", "Admin", "dilhdk", "SMS"); 
Dharman
  • 30,962
  • 25
  • 85
  • 135