28

PHP/MySQLi で 2 つの準備済みステートメントを使用して、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();

私が試したこと:

  • 準備済みステートメントを 2 つの別個のオブジェクトに移動します。
  • コードの使用:

    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
    
  • free_result() と mysqli_stmt->close() の使用

PS: 'Out of Sync' エラーは、2 番目のステートメントの '$stmt1->error' から発生します。

4

3 に答える 3

21

mysqli::query で MYSQLI_USE_RESULT を使用すると、mysqli_free_result() を呼び出さない限り、後続のすべての呼び出しでエラー Commands out of sync が返されます。

複数のストアド プロシージャを呼び出すと、「コマンドが同期されていません。現在、このコマンドを実行できません」というエラーが発生する可能性があります。これは、呼び出しの間に結果オブジェクトで close() 関数を使用している場合でも発生する可能性があります。この問題を解決するには、ストアド プロシージャを呼び出すたびに、必ず mysqli オブジェクトで next_result() 関数を呼び出してください。以下の例を参照してください。

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

これが役立つことを願っています

于 2013-01-28T12:04:31.907 に答える
8

「コマンドが同期していません。現在、このコマンドを実行することはできません」

このエラーの詳細については、mysql ドキュメントを参照してください。これらの詳細を読むと、同じ接続で別の準備済みステートメントを実行する前に、準備済みステートメント実行の結果セットを完全にフェッチする必要があることが明らかになります。

この問題は、store result 呼び出しを使用して修正できます。これは私が最初にやろうとしていたことの例です:

<?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 Notice: 未定義変数: post_title in error.php 行 41 ID: 9033 -> Array ( )

正しく機能させるために必要なことは次のとおりです。

<?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.
于 2013-01-28T12:11:59.613 に答える
4

正しいことを行い、準備済みステートメントでストアドプロシージャを使用する人向け。

出力変数をストアド プロシージャのパラメータとして使用すると、何らかの理由で 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;

これで、「コマンドが同期されていないため、現在コマンドを実行できません」というエラーが発生することなく、2 番目のストアド プロシージャを実行する準備が整いました。レコード セットで複数の値を返す場合は、次のようにループしてすべての値を取得できます。

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

ストアド プロシージャから複数のレコード セットを返す場合 (複数の選択がある場合)、$stmt->next_result(); を使用してそれらのレコード セットすべてを確認してください。

于 2013-12-28T19:21:28.100 に答える