2010-09-02 36 views
19

Tôi đang cố gắng chạy phần sau.mysqli đưa ra "Lệnh không đồng bộ" - tại sao?

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

?> 

Nếu tôi loại bỏ các nếp:

$aid = $row["agent_id"]; 

để ....

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

mọi thứ sẽ hoạt động tốt. Nếu không, tôi nhận được lỗi sau:

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

Trong nghiên cứu, tôi nghĩ rằng nó có thể là do nhiều truy vấn MySQLi chạy cùng một lúc, trong đó sử dụng mysqli_multi_query nhưng đối với tất cả các mẫu và các dữ liệu chung trong the guide làm dường như không được áp dụng.

Bất kỳ ý tưởng nào?

+0

đâu là dòng '$ date = abs (strtotime (ngày ('m/d/Y')) - strtotime (ngày ($ kdate)))/(60 * 60 * 24); } 'trong mã của bạn? Bạn nói nếu bạn loại bỏ nó, nhưng tôi không thể nhìn thấy nó ở đó. – avacariu

+0

@vlad - lời xin lỗi của tôi, cố định – JM4

Trả lời

36

Máy khách MySQL không cho phép bạn thực hiện truy vấn mới nơi vẫn còn các hàng được tìm nạp từ truy vấn đang tiến hành. Xem Commands out of sync trong tài liệu MySQL về các lỗi phổ biến.

Bạn có thể sử dụng mysqli_store_result() để tìm nạp trước tất cả các hàng từ truy vấn bên ngoài. Điều đó sẽ đệm chúng trong máy khách MySQL, do đó, từ quan điểm của máy chủ, ứng dụng của bạn đã tìm nạp tập kết quả đầy đủ. Sau đó, bạn có thể thực hiện nhiều truy vấn hơn ngay cả trong vòng lặp tìm nạp các hàng từ tập kết quả bên ngoài được đệm bây giờ.

Hoặc bạn mysqli_result::fetch_all() trả về tập hợp kết quả đầy đủ dưới dạng mảng PHP, sau đó bạn có thể lặp lại mảng đó.

Gọi thủ tục được lưu trữ là trường hợp đặc biệt, bởi vì thủ tục được lưu trữ có khả năng trả về nhiều tập kết quả, mỗi bộ có thể có các hàng riêng. Đó là lý do tại sao câu trả lời từ @ a1ex07 đề cập đến sử dụng mysqli_multi_query() và lặp cho đến mysqli_next_result() không có tập hợp kết quả nào khác. Điều này là cần thiết để đáp ứng giao thức MySQL, ngay cả khi trong trường hợp của bạn thủ tục lưu trữ của bạn có một tập kết quả duy nhất.


PS: Nhân tiện, tôi thấy bạn đang thực hiện truy vấn lồng nhau vì bạn có dữ liệu đại diện cho một hệ thống phân cấp. Bạn có thể muốn xem xét lưu trữ dữ liệu khác nhau, vì vậy bạn có thể truy vấn dữ liệu dễ dàng hơn. Tôi đã trình bày về điều này có tiêu đề Models for Hierarchical Data with SQL and PHP. Tôi cũng đề cập đến chủ đề này trong một cuốn sách của tôi SQL Antipatterns: Avoiding the Pitfalls of Database Programming.


Dưới đây là làm thế nào để thực hiện mysqli_next_result() trong CodeIgnitor 3.0.3:

On line 262 của system/database/drivers/mysqli/mysqli_driver.php thay đổi

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

này

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

Đây là một vấn đề kể từ 2.x. Tôi vừa cập nhật lên 3.x và phải sao chép bản hack này sang phiên bản mới.

+0

Cảm ơn lời khuyên tuyệt vời. Tôi đã kết thúc giải quyết câu hỏi của riêng mình (cho đến nay ...) theo cách có ý nghĩa hơn trên một trang php khác (http://php.net/manual/en/mysqli.store-result.php). Trình bày tuyệt vời bằng cách này - tôi cần phải cung cấp cho nó một số thời gian thực nhưng có vẻ valuabe. Thoạt nhìn, tuy nhiên - có thể là một bum cho tôi kể từ khi tôi đang sử dụng MySQL - Tôi chắc chắn rằng lý thuyết tương tự áp dụng – JM4

+0

Câu trả lời hay, đã giúp tôi trải qua một vấn đề tương tự. Cảm ơn – xzdead

+0

Vì vậy, ngay cả khi chúng ta chỉ có một truy vấn bằng cách sử dụng đối tượng cơ sở dữ liệu, chúng ta vẫn nên gọi 'mysqli_next_result()'? – Pachonk

3

Đơn giản, Bạn phải gọi mysqli_next_result ($ db), sau khi mysqli_free_result được gọi.

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

1

chỉ cần gọi chức năng này:

$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

Nếu bạn cũng đang thực hiện một vài cuộc gọi đến thủ tục lưu trữ, và phải đối mặt với lỗi nói trên, tôi có một giải pháp cho bạn, Ông Wayne.

IMHO, Một nơi nào đó ở dưới dòng, CALL đến Stored Procedure thực sự làm hỏng kết nối. Vì vậy, tất cả các bạn phải làm là thiết lập lại xử lý kết nối cơ sở dữ liệu.

Bạn thậm chí có thể có một chức năng ngồi trong tập tin cấu hình của bạn thực hiện điều đó cho bạn, và tất cả các bạn làm là gọi hàm này một lần trước khi thực hiện bất kỳ query hoặc CALL đến Stored Procedure

thực hiện của tôi là (chỉ cần bỏ qua $app kể từ khi tôi đang làm việc trên silex khuôn khổ nó ở đó, 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

Bạn phải đóng giữ kết nối trước bởi Stored Procedure. Thay vì đóng kết nối mỗi lần, bạn chỉ có thể sử dụng:

mysqli_next_result($conn); 
Các vấn đề liên quan