Ошибки PHP из-за ошибки синхронизации
Я использую два подготовленных оператора в PHP/MySQLi для извлечения данных из базы данных mysql. Однако, когда я запускаю инструкции, я получаю сообщение "Команды не синхронизированы, вы не можете запустить команду сейчас".
Вот мой код:
$stmt = $mysqli->prepare("SELECT id, username, password, firstname, lastname, salt FROM members WHERE email = ? LIMIT 1";
$stmt->bind_param('s', $loweredEmail);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($user_id, $username, $db_password, $firstname, $lastname, $salt);
$stmt->fetch();
$stmt->free_result();
$stmt->close();
while($mysqli->more_results()){
$mysqli->next_result();
}
$stmt1 = $mysqli->prepare("SELECT privileges FROM delegations WHERE id = ? LIMIT 1");
//This is where the error is generated
$stmt1->bind_param('s', $user_id);
$stmt1->execute();
$stmt1->store_result();
$stmt1->bind_result($privileges);
$stmt1->fetch();
Что я пробовал:
PS: ошибка "Out of Sync" исходит из второго оператора "$ stmt1- > error"
Ответы
Ответ 1
В mysqli:: query Если вы используете MYSQLI_USE_RESULT, все последующие вызовы возвращают ошибку Команды не синхронизируются, если вы не вызываете mysqli_free_result()
При вызове нескольких хранимых процедур вы можете запустить следующую ошибку: "Команды не синхронизированы, вы не можете запустить эту команду сейчас".
Это может произойти даже при использовании функции close() в объекте результата между вызовами.
Чтобы устранить проблему, не забудьте вызвать функцию next_result() объекта mysqli после каждого вызова хранимой процедуры. См. Пример ниже:
<?php
// New Connection
$db = new mysqli('localhost','user','pass','database');
// Check for errors
if(mysqli_connect_errno()){
echo mysqli_connect_error();
}
// 1st Query
$result = $db->query("call getUsers()");
if($result){
// Cycle through results
while ($row = $result->fetch_object()){
$user_arr[] = $row;
}
// Free result set
$result->close();
$db->next_result();
}
// 2nd Query
$result = $db->query("call getGroups()");
if($result){
// Cycle through results
while ($row = $result->fetch_object()){
$group_arr[] = $row;
}
// Free result set
$result->close();
$db->next_result();
}
else echo($db->error);
// Close connection
$db->close();
?>
Я надеюсь, что это поможет
Ответ 2
"Команды не синхронизированы, вы не можете запустить эту команду сейчас"
Подробности об этой ошибке можно найти в документах mysql. Чтение этих деталей дает понять, что результирующие наборы готового выполнения инструкции должны быть полностью загружены перед выполнением другого подготовленного оператора в том же соединении.
Фиксирование проблемы может быть выполнено с помощью вызова результата хранилища. Вот пример того, что я изначально пытался сделать:
<?php
$db_connection = new mysqli('127.0.0.1', 'user', '', 'test');
$post_stmt = $db_connection->prepare("select id, title from post where id = 1000");
$comment_stmt = $db_connection->prepare("select user_id from comment where post_id = ?");
if ($post_stmt->execute())
{
$post_stmt->bind_result($post_id, $post_title);
if ($post_stmt->fetch())
{
$comments = array();
$comment_stmt->bind_param('i', $post_id);
if ($comment_stmt->execute())
{
$comment_stmt->bind_result($user_id);
while ($comment_stmt->fetch())
{
array_push($comments, array('user_id' => $user_id));
}
}
else
{
printf("Comment statement error: %s\n", $comment_stmt->error);
}
}
}
else
{
printf("Post statement error: %s\n", $post_stmt->error);
}
$post_stmt->close();
$comment_stmt->close();
$db_connection->close();
printf("ID: %d -> %s\n", $post_id, $post_title);
print_r($comments);
?>
Приведенное выше приведет к следующей ошибке:
Ошибка описания комментариев: команды не синхронизированы; вы не можете запустить эту команду сейчас
Примечание PHP: переменная Undefined: post_title в файле error.php в строке 41
ID: 9033 → массив
(
)
Вот что нужно сделать, чтобы он работал правильно:
<?php
$db_connection = new mysqli('127.0.0.1', 'user', '', 'test');
$post_stmt = $db_connection->prepare("select id, title from post where id = 1000");
$comment_stmt = $db_connection->prepare("select user_id from comment where post_id = ?");
if ($post_stmt->execute())
{
$post_stmt->store_result();
$post_stmt->bind_result($post_id, $post_title);
if ($post_stmt->fetch())
{
$comments = array();
$comment_stmt->bind_param('i', $post_id);
if ($comment_stmt->execute())
{
$comment_stmt->bind_result($user_id);
while ($comment_stmt->fetch())
{
array_push($comments, array('user_id' => $user_id));
}
}
else
{
printf("Comment statement error: %s\n", $comment_stmt->error);
}
}
$post_stmt->free_result();
}
else
{
printf("Post statement error: %s\n", $post_stmt->error);
}
$post_stmt->close();
$comment_stmt->close();
$db_connection->close();
printf("ID: %d -> %s\n", $post_id, $post_title);
print_r($comments);
?>
Несколько вещей, чтобы отметить пример выше:
The bind and fetch on the statement still works correctly.
Make sure the results are freed when the processing is done.
Ответ 3
Для тех из вас, кто поступает правильно и использует хранимые процедуры с подготовленными операторами.
По какой-то причине mysqli не может освобождать ресурсы при использовании выходной переменной в качестве параметра хранимой процедуры. Чтобы исправить это, просто верните набор записей внутри тела процедуры вместо сохранения значения в выходной переменной/параметре.
Например, вместо SET outputVar = LAST_INSERT_ID(); вы можете иметь SELECT LAST_INSERT_ID(); Затем в PHP я получаю возвращаемое значение следующим образом:
$query= "CALL mysp_Insert_SomeData(?,?)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("is", $input_param_1, $input_param_2);
$stmt->execute() or trigger_error($mysqli->error); // trigger_error here is just for troubleshooting, remove when productionizing the code
$stmt->store_result();
$stmt->bind_result($output_value);
$stmt->fetch();
$stmt->free_result();
$stmt->close();
$mysqli->next_result();
echo $output_value;
Теперь вы готовы выполнить вторую хранимую процедуру, не выполнив ошибку "Команды не синхронизируются, вы не можете запустить команду сейчас". Если вы возвращаете более одного значения в наборе записей, вы можете прокручивать и извлекать все из них следующим образом:
while ($stmt->fetch()) {
echo $output_value;
}
Если вы возвращаете более одного набора записей из сохраненного proc (у вас есть несколько выборок), убедитесь, что вы прошли через все эти записи с помощью $stmt- > next_result();