2010-09-02 16 views
19

Sto cercando di eseguire quanto segue.mysqli errore "Comandi fuori sincrono" - perché?

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

?> 

se rimuovere le linee da:

$aid = $row["agent_id"]; 

a ....

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

tutto funzionerà bene. In caso contrario, ricevo il seguente errore:

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

nella ricerca, penso che potrebbe essere dovuto a più query MySQLi funzionare allo stesso tempo, in cui utilizzando mysqli_multi_query ma per tutti i campioni e dei dati generali in the guide fa non sembra essere applicabile.

Qualche idea?

+0

Dove è la linea '$ date = abs (strtotime (data ('m/d/Y')) - strtotime (data ($ kdate)))/(60 * 60 * 24); } 'nel tuo codice? Hai detto di rimuoverlo, ma non riesco a vederlo lì. – avacariu

+0

@vlad - le mie scuse, risolto – JM4

risposta

36

Il client MySQL non consente di eseguire una nuova query in cui ci sono ancora file da recuperare da una query in corso. Vedere Commands out of sync nel documento MySQL sugli errori comuni.

È possibile utilizzare mysqli_store_result() per prelevare preventivamente tutte le righe dalla query esterna. Questo li bufferizzerà nel client MySQL, quindi dal punto di vista del server la tua app ha recuperato il set di risultati completo. Quindi è possibile eseguire più query anche in un ciclo di recupero di righe dal set di risultati esterno ora bufferizzato.

Oppure mysqli_result::fetch_all() che restituisce il set di risultati completo come array PHP e quindi è possibile eseguire il loop su tale array.

La chiamata di stored procedure è un caso speciale, poiché una stored procedure ha la possibilità di restituire più set di risultati, ognuno dei quali può avere il proprio set di righe. Ecco perché la risposta di @ a1ex07 menziona utilizzando mysqli_multi_query() e il ciclo fino a mysqli_next_result() non ha più set di risultati. Questo è necessario per soddisfare il protocollo MySQL, anche se nel tuo caso la procedura memorizzata ha un singolo set di risultati.


PS: A proposito, vedo che stai facendo le query nidificate perché hai dati che rappresentano una gerarchia. Potresti considerare di archiviare i dati in modo diverso, in modo da poterli interrogare più facilmente. Ho fatto una presentazione su questo titolo dal titolo Models for Hierarchical Data with SQL and PHP. Copro anche questo argomento in un capitolo del mio libro SQL Antipatterns: Avoiding the Pitfalls of Database Programming.


Ecco come implementare mysqli_next_result() in CodeIgnitor 3.0.3:

on line 262 del system/database/drivers/mysqli/mysqli_driver.php cambiamento

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

a questo

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

Questo è stato un problema dal 2.x. Ho appena aggiornato 3.x e ho dovuto copiare questo hack sulla nuova versione.

+0

Grazie per l'ottimo consiglio. Ho finito per risolvere la mia domanda (finora ...) in un modo che aveva più senso su un'altra pagina php (http://php.net/manual/en/mysqli.store-result.php). Grande presentazione a proposito - ho bisogno di dargli un po 'di tempo reale, ma sembra essere un valore. A prima vista, tuttavia, potrebbe essere un barbone per me dal momento che sto usando MySQL - sono sicuro che teorie analoghe si applicano – JM4

+0

Una buona risposta, mi ha aiutato a passare attraverso un problema simile. Grazie – xzdead

+0

Quindi, anche se abbiamo solo una query che utilizza l'oggetto del database, dovremmo comunque chiamare 'mysqli_next_result()'? – Pachonk

3

Semplicemente, Devi chiamare mysqli_next_result ($ db), dopo che mysqli_free_result è stato chiamato.

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

1

semplicemente chiamare questa funzione:

$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

Se si sta anche facendo alcune chiamate alle stored procedure, e di fronte l'errore di cui sopra, ho una soluzione per voi, signor Wayne .

IMHO, qualche parte lungo la linea, il CALL a Stored Procedure pasticci effettivamente la connessione. Quindi tutto ciò che devi fare è resettare l'handle di connessione al database.

si potrebbe anche avere una funzione seduti nel vostro file di configurazione fare proprio questo per te, e tutto quello che fai è chiamare tale funzione, una volta prima di fare qualsiasi query o CALL al Stored Procedure

mio attuazione è (basta ignorare il $app dal momento sto lavorando su silex quadro è lì, 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']; 
} 
0

si deve chiudere precedente hold connessione stored procedure. Invece di chiudere il collegamento ogni volta, si può semplicemente utilizzare:

mysqli_next_result($conn); 
Problemi correlati