Подтвердить что ты не робот

Mysqli дает ошибку "Commands out of sync" - почему?

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

<?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, но для всех образцов и общих данных в руководство, похоже, не применимо.

Любые идеи?

4b9b3361

Ответ 1

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

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

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

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


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


Вот как реализовать 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 и должен был скопировать этот хак в новую версию.

Ответ 2

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

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

Ответ 3

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

$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);
            }
        }
    }

Ответ 4

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

mysqli_next_result($conn);

Ответ 5

Если вы также выполняете несколько вызовов хранимых процедур и сталкиваетесь с вышеупомянутой ошибкой, у меня есть решение для вас, Mr. Wayne.

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

У вас может даже быть функция, сидящая в вашем файле конфигурации, которая делает именно это для вас, и все, что вы делаете, - это вызов этой функции один раз, прежде чем сделать query или CALL в Stored Procedure

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

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'];
}