2010-09-02 19 views
19

我試圖運行以下內容。mysqli給「命令不同步」錯誤 - 爲什麼?

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

?> 

如果我刪除線:

$aid = $row["agent_id"]; 

到....

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

一切都將正常工作。如果不是這樣,我得到以下錯誤:

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

在研究,我認爲這可能是由於多個庫MySQLi查詢同時運行,在使用mysqli_multi_query但對於the guide所有樣品和通用數據不似乎不適用。

任何想法?

+0

線在哪裏'$日期= ABS(的strtotime(日期( 'M/d/Y')) - 的strtotime(日期($ kdate) ))/(60 * 60 * 24); ''在你的代碼中?你說如果你刪除它,但我不能在那裏看到它。 – avacariu 2010-09-02 23:43:36

+0

@vlad - 我的道歉,修好了 – JM4 2010-09-02 23:48:12

回答

36

MySQL客戶端不允許您執行新的查詢,其中仍有行要從正在進行的查詢中獲取。有關常見錯誤,請參閱MySQL文檔中的Commands out of sync

您可以使用mysqli_store_result()預取外部查詢中的所有行。這會將它們緩存在MySQL客戶端中,因此從服務器的角度來看,您的應用程序已經獲取了完整的結果集。然後,即使在從現在緩衝的外部結果集中獲取行的循環中,您也可以執行更多查詢。

或者您mysqli_result::fetch_all()它將完整的結果集作爲PHP數組返回,然後您可以遍歷該數組。

調用存儲過程是一種特殊情況,因爲存儲過程有可能返回多個結果集,每個結果集都可能有自己的一組行。這就是爲什麼@ a1ex07的答案提到使用mysqli_multi_query()並循環直到mysqli_next_result()沒有更多的結果集。這對於滿足MySQL協議是必要的,即使在你的情況下你的存儲過程只有一個結果集。


PS:順便說一句,我看你正在做嵌套查詢,因爲你有代表層次結構的數據。您可能需要考慮以不同方式存儲數據,以便您可以更輕鬆地查詢它。我做了一個關於這個標題爲Models for Hierarchical Data with SQL and PHP的介紹。我還在我的書SQL Antipatterns: Avoiding the Pitfalls of Database Programming的一章中介紹了這個主題。


這裏是如何在CodeIgnitor 3.0.3實施mysqli_next_result()

system/database/drivers/mysqli/mysqli_driver.php變化

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

的262線,這

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

這一直是一個問題自2.x.我剛剛更新到3.x,不得不將這個黑客複製到新版本。

+0

謝謝你的好建議。我結束瞭解決我自己的問題(到目前爲止),在另一個PHP頁面更有意義(http://php.net/manual/en/mysqli.store-result.php)。順便提一下,我需要給它一些實時的,但看起來很有價值。乍一看,但是 - 可能對我來說是一個屁股,因爲我使用的是MySQL - 我相信類似的理論適用於 – JM4 2010-09-03 01:05:17

+0

好的答案,幫助我解決了類似的問題。謝謝 – xzdead 2013-07-31 15:07:05

+0

所以,即使我們只有一個使用數據庫對象的查詢,我們仍然應該調用'mysqli_next_result()'? – Pachonk 2014-03-25 05:31:34

3

只需, 調用mysqli_free_result之後,您必須調用mysqli_next_result($ db)。

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

1

簡單地調用這個函數:

$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

如果你也做了一些存儲過程調用,並面臨上述錯誤,我有你的解決方案,韋恩先生

恕我直言,在某個地方,CALLStored Procedure實際上混淆了連接。所以你所要做的就是重置數據庫連接句柄。

你甚至可以有一個功能,坐在你的配置文件只是爲你做,而你要做的就是做任何queryCALLStored Procedure

我實現(只是忽略前一次調用該函數$app因爲我對silex框架它就在那裏,情況因人而異)

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

工作你必須通過存儲過程來關閉以前的連接保持。 不是每次都關閉連接,你可以簡單地使用:

mysqli_next_result($conn); 
相關問題