2010-09-02 13 views
19

Estoy tratando de ejecutar lo siguiente.mysqli dando el error "Comandos no sincronizados" - ¿por qué?

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

?> 

Si quito las líneas de:

$aid = $row["agent_id"]; 

a ....

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

todo funcionará bien. Si no, me sale el siguiente error:

Commands out of sync; you can't run this command now

en la investigación, creo que podría ser debido a varias consultas MySQLi ejecutar al mismo tiempo, en el que el uso de mysqli_multi_query sino para todas las muestras y datos generales en the guide hace no parece ser aplicable.

¿Alguna idea?

+0

Dónde está la línea 'date $ = abs (strtotime (fecha ('M/D/Y')) - strtotime (fecha ($ kdate)))/(60 * 60 * 24); } 'en tu código? Dijiste que si lo eliminas, pero no puedo verlo allí. – avacariu

+0

@vlad - mis disculpas, corregido – JM4

Respuesta

36

El cliente MySQL no le permiten ejecutar una nueva consulta, donde todavía hay filas a captar de una consulta en curso. Consulte Commands out of sync en el documento de MySQL sobre errores comunes.

Puede utilizar mysqli_store_result() precargar todas las filas de la consulta externa. Eso los amortiguará en el cliente MySQL, por lo que desde el punto de vista del servidor su aplicación ha obtenido el conjunto completo de resultados. A continuación, puede ejecutar más consultas incluso en un bucle de obtención de filas del conjunto de resultados externo ahora búfer.

O mysqli_result::fetch_all() que devuelve el resultado conjunto completo como una matriz PHP, y luego puede recorrer más de esa matriz.

Llamada a procedimientos almacenados es un caso especial, porque un procedimiento almacenado tiene el potencial de devolver varios conjuntos de resultados, cada uno de los cuales puede tener su propio conjunto de filas. Es por eso que la respuesta de @ a1ex07 menciona el uso de mysqli_multi_query() y bucle hasta mysqli_next_result() no tiene más conjuntos de resultados. Esto es necesario para satisfacer el protocolo MySQL, incluso si en su caso su procedimiento almacenado tiene un solo conjunto de resultados.


PD: A propósito, veo que está haciendo las consultas anidadas porque tiene datos que representan una jerarquía. Es posible que desee considerar almacenar los datos de manera diferente, para poder consultarlos más fácilmente. Hice una presentación sobre esto titulado Models for Hierarchical Data with SQL and PHP. También cubro este tema en un capítulo de mi libro SQL Antipatterns: Avoiding the Pitfalls of Database Programming.


Aquí es cómo implementar mysqli_next_result() en CodeIgnitor 3.0.3:

En la línea 262 de system/database/drivers/mysqli/mysqli_driver.php cambio

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

a este

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

Este ha sido un problema desde 2.x. Acabo de actualizar a 3.x y tuve que copiar este truco a la nueva versión.

+0

Gracias por el gran consejo. Terminé resolviendo mi propia pregunta (hasta ahora ...) de una manera que tenía más sentido en otra página php (http://php.net/manual/en/mysqli.store-result.php). Gran presentación por cierto, tengo que darle un tiempo real, pero parece valuabe. A primera vista, sin embargo, puede ser un fastidio para mí ya que estoy usando MySQL - estoy seguro de que se aplican teorías similares – JM4

+0

Una buena respuesta, me ayudó a pasar por un problema similar. Gracias – xzdead

+0

Entonces, incluso si solo tenemos una consulta utilizando el objeto de la base de datos, todavía debemos llamar a 'mysqli_next_result()'? – Pachonk

3

Simplemente, Tienes que llamar mysqli_next_result ($ db), después de mysqli_free_result se llama.

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

1

simplemente llamar a esta función:

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

Si también está haciendo algunas llamadas a procedimientos almacenados, y frente al error antes mencionado, tengo una solución para usted, Sr. Wayne .

en mi humilde opinión, En algún lugar de la línea, el CALL-Stored Procedure se mete en realidad la conexión. Entonces, todo lo que tiene que hacer es restablecer el identificador de conexión de la base de datos.

Usted podría incluso tener una función sentado en su archivo de configuración haciendo eso para usted, y lo único que hace es llamar a esa función una vez antes de hacer cualquier query o CALL a la Stored Procedure

Mi aplicación es (simplemente ignorar la $app ya estoy trabajando en silex marco que está ahí, tu caso es distinto)

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

hay que cerrar bodega conexión previa al procedimiento almacenado. En lugar de cerrar conexión cada vez, sólo tiene que utilizar:

mysqli_next_result($conn); 
Cuestiones relacionadas