2009-11-05 26 views
13

Tôi có một thủ tục lưu sẵn có nhiều tập kết quả. Làm cách nào để chuyển sang tập kết quả thứ 2 trong mysqli để nhận các kết quả đó?Lấy ra nhiều tập kết quả với thủ tục lưu sẵn trong php/mysqli

Hãy nói rằng nó là một proc được lưu trữ như:

create procedure multiples(param1 INT, param2 INT) 
BEGIN 

SELECT * FROM table1 WHERE id = param1; 

SELECT * FROM table2 WHERE id = param2; 

END $$ 

Các PHP là một cái gì đó như thế này:

$stmt = mysqli_prepare($db, 'CALL multiples(?, ?)'); 

mysqli_stmt_bind_param($stmt, 'ii', $param1, $param2); 

mysqli_stmt_execute($stmt); 

mysqli_stmt_bind_result($stmt, $id); 

Sau đó, đây là một phần tôi không thể có được để làm việc. Tôi đã thử sử dụng mysqli_next_result để chuyển sang tập kết quả tiếp theo, nhưng không thể làm cho nó hoạt động. Chúng tôi đã làm cho nó hoạt động với mysqli_store_result và mysqli_fetch_assoc/array/row, nhưng vì một lý do nào đó tất cả các int được trả về dưới dạng các chuỗi trống.

Bất kỳ ai khác gặp phải điều này và có giải pháp?

+0

Thủ tục gọi trả lại đúng bằng cách sử dụng mysqli_multi_query() thay vì câu lệnh đã chuẩn bị chưa? – gapple

+0

Ồ, xin lỗi. Phản ứng đầu tiên của tôi không đọc chính xác bình luận của bạn. Chúng ta cần sử dụng các câu lệnh đã được chuẩn bị, nhưng truy vấn là đúng và làm việc cho tập kết quả đầu tiên. Tôi chỉ không thể tìm ra cách để chuyển nó đến tập kết quả thứ 2. – MacAnthony

Trả lời

13

Tôi nghĩ rằng bạn đang thiếu một cái gì đó ở đây (sau đây chưa được thử nghiệm):

$stmt = mysqli_prepare($db, 'CALL multiples(?, ?)'); 
mysqli_stmt_bind_param($stmt, 'ii', $param1, $param2); 
mysqli_stmt_execute($stmt); 
// fetch the first result set 
$result1 = mysqli_use_result($db); 
// you have to read the result set here 
while ($row = $result1->fetch_assoc()) { 
    printf("%d\n", $row['id']); 
} 
// now we're at the end of our first result set. 
mysqli_free_result($result1); 

//move to next result set 
mysqli_next_result($db); 
$result2 = mysqli_use_result($db); 
// you have to read the result set here 
while ($row = $result2->fetch_assoc()) { 
    printf("%d\n", $row['id']); 
} 
// now we're at the end of our second result set. 
mysqli_free_result($result2); 

// close statement 
mysqli_stmt_close($stmt); 

Sử dụng PDO mã của bạn sẽ trông như thế:

$stmt = $db->prepare('CALL multiples(:param1, :param2)'); 
$stmt->execute(array(':param1' => $param1, ':param2' => $param2)); 
// read first result set 
while ($row = $stmt->fetch()) { 
    printf("%d\n", $row['id']); 
} 
$stmt->nextRowset(); 
// read second result set 
while ($row = $stmt->fetch()) { 
    printf("%d\n", $row['id']); 
} 

Nhưng tôi đã nghe nói rằng PDOStatement::nextRowset() không được triển khai với MySQL PDO driver khiến không thể truy xuất nhiều tập hợp kết quả:

Vì vậy, tùy thuộc vào phiên bản PHP của bạn, bạn sẽ phải gắn bó với mysqli -solution của bạn. Nhân tiện: bạn có sử dụng kiểu thủ tục cố ý không? Sử dụng phong cách hướng đối tượng với mysqli sẽ làm cho mã của bạn trông hấp dẫn hơn một chút (ý kiến ​​cá nhân của tôi).

+0

Chúng tôi biết PDO và vẫn cần phải đánh giá nó để xem nó có tốt hơn mysqli hay không, nhưng đây là một dự án hiện có và thay thế lớp DB là không thực tế. Trộn 2 lớp DB chỉ là thiết kế tồi, IMO. – MacAnthony

+0

Có, bạn nói đúng, rằng tôi đã bỏ ra dòng mysqli_stmt_fetch ($ stmt). Một nhà phát triển trước đã sử dụng các đối tượng mysqli-stmt thay vì các đối tượng tập kết quả. Như đã nói, khi chúng tôi thử kết quả được đặt bằng fetch_assoc, tất cả các cột int được trả về dưới dạng các chuỗi trống. – MacAnthony

+0

Đây là câu hỏi và câu trả lời cũ, nhưng giải pháp mysqli không còn hoạt động nữa ... 'mysqli_use_result' sẽ chỉ trả lại' false' sau 'mysqli_stmt_execute' ...' mysqli_use_result' chỉ có thể được sử dụng sau "truy vấn" –

1

Dường như MySQLi chỉ có thể hỗ trợ nhiều bộ kết quả qua mysqli_multi_query(), vì các đối tượng MySQLi_STMT hoạt động khác với các đối tượng MySQLi_Result.

PDO có vẻ hơi trừu tượng hơn, với các đối tượng PDOStatement có thể xử lý nhiều tập hợp kết quả cho cả truy vấn thông thường (PDO::query) và câu lệnh chuẩn bị (PDO:prepare).

+0

cũng có thể lặp qua nhiều tập kết quả bằng '$ stmt-> get_results()' ... '$ stmt-> next_result()' .. cả hai hàm/phương thức chỉ có sẵn với "MySQL Native Driver" –

0

Điều này đã làm việc thực sự tốt đối với tôi, nó sẽ giải quyết (ví dụ) như nhiều Danh sách Chọn như có trong SP của bạn. Lưu ý làm thế nào bạn phải đóng $ gọi TRƯỚC sau đó bạn có thể nhận được các thông số OUT từ SP của bạn ...

?><pre><? 
$call = mysqli_prepare($db, 'CALL test_lists(?, ?, @result)'); 
if($call == false) { 
    echo "mysqli_prepare (\$db, 'CALL test_lists(?, ?, @result) FAILED!!!\n"; 
} else { 
    // A couple of example IN parameters for your SP... 
    $s_1 = 4; 
    $s_2 = "Hello world!"; 

    // Here we go (safer way of avoiding SQL Injections)... 
    mysqli_stmt_bind_param($call, 'is', $s_1, $s_2); 

    // Make the call... 
    if(mysqli_stmt_execute($call) == false) { 
     echo "mysqli_stmt_execute(\$call) FAILED!!!\n"; 
    } else { 
     //print_r($call); 

     // Loop until we run out of Recordsets... 
     $set = 0; 
     while ($recordset = mysqli_stmt_get_result($call)) { 
      ++$set; 
      //print_r($recordset); 
      echo "\nRecordset #" . $set . "...\n"; 
      if ($recordset->num_rows > 0) { 
       $ctr = 0; 
       while ($row = $recordset->fetch_assoc()) { 
        ++$ctr; 
        //print_r($row); 
        echo "\t" . $ctr . ": "; 
        forEach($row as $key => $val) { 
         echo "[" . $key . "] " . $val . "\t"; 
        } 
        echo "\n"; 
       } 
      } 
      echo $recordset->num_rows . " record" . ($recordset->num_rows == 1 ? "" : "s") . ".\n"; 
      // Clean up, ready for next iteration... 
      mysqli_free_result($recordset); 

      // See if we can get another Recordset... 
      mysqli_stmt_next_result($call); 
     } 

     // Then you have to close the $call... 
     mysqli_stmt_close($call); 
     // ...in order to get to the SP's OUT parameters... 
     $select = mysqli_query($db, "SELECT @result"); 
     $row = mysqli_fetch_row($select); 
     $result = $row[0]; 
     echo "\nOUT @result = " . $result . "\n"; 
    } 
} 
?></pre><? 

Và đây là những gì đầu ra từ đoạn mã trên trông giống như sử dụng test_lists SP của tôi ...

Recordset #1... 
    1: [s_1] 4 [user_name] Andrew Foster 
    2: [s_1] 4 [user_name] Cecil 
    3: [s_1] 4 [user_name] Sheff 
3 records. 

Recordset #2... 
    1: [s_2] Hello world! [section_description] The Law 
    2: [s_2] Hello world! [section_description] History 
    3: [s_2] Hello world! [section_description] Wisdom Literature 
    4: [s_2] Hello world! [section_description] The Prophets 
    5: [s_2] Hello world! [section_description] The Life of Jesus and the Early Church  
    6: [s_2] Hello world! [section_description] Letters from the Apostle Paul 
    7: [s_2] Hello world! [section_description] Other Letters from Apostles and Prophets 
    8: [s_2] Hello world! [section_description] Prophecy - warnings for the present and revelation of the future 
8 records. 

OUT @result = 16 
Các vấn đề liên quan