Почему mysqli выдает ошибку «Команды не синхронизированы»? - PullRequest
20 голосов
/ 03 сентября 2010

Я пытаюсь запустить следующее.

<?php

$db = mysqli_connect("localhost","user","pw") or die("Database error");
mysqli_select_db($db, "database");

$agtid = $_POST['level'];

$sql = sprintf("call agent_hier(%d)", $agtid);

$result = mysqli_query($db, $sql) or exit(mysqli_error($db));

if ($result) {
    echo "<table border='1'>
        <tr><th>id</th>
        <th>name</th>
        <th>parent_id</th>
        <th>parent_name</th>
        <th>level</th>
        <th>email</th></tr>";

    while ($row = mysqli_fetch_assoc($result)) 
    {
        $aid = $row["id"];
        $sql2 = "SELECT * FROM members WHERE MEMNO = '$aid'";
        $result2 = mysqli_query($db,$sql2) or exit(mysqli_error($db));

            while ($newArray = mysqli_fetch_array($result2)) {
                $fname = $newArray['FNAME'];
                $lname = $newArray['LNAME'];
                $mi = $newArray['MI'];  
                $address = $newArray['ADDRESS'];    
                $city = $newArray['CITY'];  
                $state = $newArray['STATE'];    
                $zip = $newArray['ZIP'];
                            $kdate = $newArray['KDATE'];
                $date = abs(strtotime(date('m/d/Y')) - strtotime(date($kdate))) / (60 * 60 * 24);
            }

        echo sprintf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
            $row["id"],$row["name"],
            $row["parent_id"],$row["parent_name"],
            $row["level"],$row["email"]);
    }

    echo "</table>";
}

mysqli_free_result($result);
mysqli_close($db);

?>

Если удалить строки из:

  $aid = $row["agent_id"];

до ....

  $date = abs(strtotime(date('m/d/Y')) - strtotime(date($kdate))) / (60 * 60 * 24);
  }

все будет работать нормально. Если нет, я получаю следующую ошибку:

Команды не синхронизированы; Вы не можете запустить эту команду сейчас

В исследованиях, я думаю, это может быть связано с одновременным выполнением нескольких запросов MySQLi, в которых используется mysqli_multi_query, но для всех примеров и общих данных в руководство не выглядит применимо.

Есть идеи?

Ответы [ 5 ]

38 голосов
/ 03 сентября 2010

Клиент MySQL не позволяет вам выполнить новый запрос, если все еще есть строки, которые должны быть извлечены из текущего запроса. См. Команды не синхронизированы в документе MySQL по распространенным ошибкам.

Вы можете использовать mysqli_store_result() для предварительной выборки всех строк из внешнего запроса. Это буферизует их в клиенте MySQL, поэтому с точки зрения сервера ваше приложение получило полный набор результатов. Затем вы можете выполнить больше запросов даже в цикле выборки строк из буферизованного внешнего набора результатов.

Или вы mysqli_result::fetch_all(), который возвращает полный набор результатов в виде массива PHP, а затем вы можете выполнить цикл по этому массиву.

Вызов хранимых процедур является особым случаем, потому что хранимая процедура может возвращать несколько результирующих наборов, каждый из которых может иметь свой собственный набор строк. Вот почему в ответе @ a1ex07 упоминается использование mysqli_multi_query() и цикл до тех пор, пока у mysqli_next_result() больше не будет наборов результатов. Это необходимо для удовлетворения протокола MySQL, даже если в вашем случае ваша хранимая процедура имеет один набор результатов.


PS: Кстати, я вижу, что вы делаете вложенные запросы, потому что у вас есть данные, представляющие иерархию. Возможно, вы захотите сохранить данные по-другому, чтобы вам было проще их запрашивать. Я сделал презентацию об этом под названием Модели для иерархических данных с SQL и PHP . Я также освещаю эту тему в главе моей книги Антипаттерны SQL: предотвращение ловушек программирования баз данных .


Вот как реализовать mysqli_next_result() в CodeIgnitor 3.0.3:

В строке 262 из system/database/drivers/mysqli/mysqli_driver.php изменить

protected function _execute($sql)
{
    return $this->conn_id->query($this->_prep_query($sql));
}

к этому

protected function _execute($sql)
{
    $results = $this->conn_id->query($this->_prep_query($sql));
    @mysqli_next_result($this->conn_id); // Fix 'command out of sync' error
    return $results;
}

Эта проблема возникает с 2.x. Я только что обновился до 3.x и мне пришлось скопировать этот хак в новую версию.

3 голосов
/ 26 июля 2011

Просто, Вы должны вызвать mysqli_next_result ($ db) после вызова mysqli_free_result.

mysqli_free_result ($ результат); mysqli_next_result ($ дБ) mysqli_close ($ дБ);

2 голосов
/ 18 сентября 2014

просто вызовите эту функцию:

$this->free_result();

function free_result() {
        while (mysqli_more_results($this->conn) && mysqli_next_result($this->conn)) {

            $dummyResult = mysqli_use_result($this->conn);

            if ($dummyResult instanceof mysqli_result) {
                mysqli_free_result($this->conn);
            }
        }
    }
0 голосов
/ 11 января 2017

Вы должны закрыть предыдущее удержание соединения с помощью хранимой процедуры.Вместо того, чтобы закрывать соединение каждый раз, вы можете просто использовать:

mysqli_next_result($conn);
0 голосов
/ 07 октября 2015

Если вы также делаете несколько обращений к хранимым процедурам и сталкиваетесь с вышеупомянутой ошибкой, у меня есть решение для вас, Мистер.Уэйн .

ИМХО, где-то внизу линии от CALL до Stored Procedure фактически портит соединение.Поэтому все, что вам нужно сделать, это сбросить дескриптор соединения с базой данных.

Вы могли бы даже иметь функцию, находящуюся в вашем конфигурационном файле, которая будет делать именно это для вас, и все, что вам нужно сделать, это вызвать эту функцию один раз перед выполнением любого * 1009.* или CALL до Stored Procedure

Моя реализация (просто игнорируйте $app, так как я работаю над silex framework, он там, YMMV) * ​​1016 *

function flushhandle() {

    global $app;
    global $db_host;
    global $db_user;
    global $db_pass;
    global $db_name;
    $app['mysqlio']->close();
    $app['mysqlio'] = new mysqli($db_host, $db_user, $db_pass, $db_name);
    return $app['mysqlio'];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...