web-dev-qa-db-fra.com

PHP Erreur de commande hors synchronisation

J'utilise deux déclarations préparées en PHP/MySQLi pour récupérer les données d'une base de données mysql. Cependant, lorsque j'exécute les instructions, j'obtiens l'erreur "Commandes désynchronisées, vous ne pouvez pas exécuter la commande maintenant".

Voici mon code:

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

Ce que j'ai essayé:

  • Déplacement des instructions préparées vers deux objets distincts.
  • En utilisant le code:

    while($mysqli->more_results()){
        $mysqli->next_result();
    }
    //To make sure that no stray result data is left in buffer between the first
    //and second statements
    
  • Utilisation de free_result () et mysqli_stmt-> close ()

PS: L'erreur "Out of Sync" provient de la "$ stmt1-> error" de la deuxième instruction

26
user191125

Dans mysqli :: query Si vous utilisez MYSQLI_USE_RESULT, tous les appels suivants renverront des commandes d'erreur non synchronisées, sauf si vous appelez mysqli_free_result ()

Lorsque vous appelez plusieurs procédures stockées, vous pouvez rencontrer l'erreur suivante: "Commandes désynchronisées; vous ne pouvez pas exécuter cette commande maintenant". Cela peut se produire même lorsque vous utilisez la fonction close () sur l'objet résultat entre les appels. Pour résoudre le problème, n'oubliez pas d'appeler la fonction next_result () sur l'objet mysqli après chaque appel de procédure stockée. Voir l'exemple ci-dessous:

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

J'espère que cela vous aidera

15
G. N. Vashishtha

"Commandes désynchronisées; vous ne pouvez pas exécuter cette commande maintenant"

Des détails sur cette erreur peuvent être trouvés dans les documents mysql. La lecture de ces détails montre clairement que les jeux de résultats d'une exécution d'instruction préparée doivent être récupérés complètement avant d'exécuter une autre instruction préparée sur la même connexion.

La résolution du problème peut être effectuée à l'aide de l'appel de résultat du magasin. Voici un exemple de ce que j'essayais initialement de faire:

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

Ce qui précède entraînera l'erreur suivante:

Erreur de déclaration de commentaire: commandes non synchronisées; vous ne pouvez pas exécuter cette commande maintenant

Avis PHP: Variable non définie: post_title dans error.php sur la ligne 41 ID: 9033 -> Array ()

Voici ce qui doit être fait pour le faire fonctionner correctement:

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

Quelques points à noter sur l'exemple ci-dessus:

The bind and fetch on the statement still works correctly.
Make sure the results are freed when the processing is done.
6
G. N. Vashishtha

Pour ceux d'entre vous qui font la bonne chose et utilisent des procédures stockées avec des instructions préparées.

Pour une raison quelconque, mysqli ne peut pas libérer les ressources lors de l'utilisation d'une variable de sortie comme paramètre dans le proc stocké. Pour résoudre ce problème, renvoyez simplement un jeu d'enregistrements dans le corps de la procédure au lieu de stocker la valeur dans une variable/paramètre de sortie.

Par exemple, au lieu d'avoir SET outputVar = LAST_INSERT_ID (); vous pouvez avoir SELECT LAST_INSERT_ID (); Puis en PHP j'obtiens la valeur retournée comme ceci:

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

Vous êtes maintenant prêt à exécuter une deuxième procédure stockée sans avoir l'erreur "Commandes désynchronisées, vous ne pouvez pas exécuter la commande maintenant". Si vous renvoyiez plusieurs valeurs dans le jeu d'enregistrements, vous pouvez les parcourir et les récupérer toutes comme ceci:

while ($stmt->fetch()) {
    echo $output_value;
}

Si vous retournez plusieurs jeux d'enregistrements à partir du proc stocké (vous avez plusieurs sélections), assurez-vous de parcourir tous ces jeux d'enregistrements en utilisant $ stmt-> next_result ();

3
Dimitar Darazhanski