2009-11-05 24 views
13

我有一個具有多個結果集的存儲過程。我如何前進到mysqli中的第二個結果集以獲得這些結果?使用存儲過程在php/mysqli中檢索多個結果集

比方說,這就像一個存儲過程:

create procedure multiples(param1 INT, param2 INT) 
BEGIN 

SELECT * FROM table1 WHERE id = param1; 

SELECT * FROM table2 WHERE id = param2; 

END $$ 

的PHP是這樣的:

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

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

mysqli_stmt_execute($stmt); 

mysqli_stmt_bind_result($stmt, $id); 

然後,這是我不能得到工作的一部分。我嘗試使用mysqli_next_result移動到下一個結果集,但無法使其工作。我們確實讓它與mysqli_store_result和mysqli_fetch_assoc/array/row一起工作,但由於某些原因,所有的ints都會返回爲空字符串。

任何人遇到此問題並有解決方案嗎?

+0

過程調用是否使用mysqli_multi_query()而不是預準備語句正確返回? – gapple 2009-11-05 21:44:43

+0

哦,對不起。我的第一個迴應是沒有正確閱讀你的評論。我們需要使用準備好的語句,但查詢是正確的並且適用於第一個結果集。我無法弄清楚如何將它提升到第二個結果集。 – MacAnthony 2009-11-05 21:50:09

回答

13

我覺得你在這裏失去了一些東西(以下尚未經過測試):

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

使用PDO你的代碼看起來像:

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

但我聽說PDOStatement::nextRowset()沒有用MySQL PDO driver實現,因此無法檢索多個結果集:

所以,這取決於你的PHP版本,你必須堅持你的mysqli - 溶液。順便說一句:你故意使用程序風格嗎?使用面向對象的風格與mysqli會讓你的代碼看起來更吸引人(我的個人意見)。

+0

我們知道PDO並且仍然需要評估它是否比mysqli更好,但是這是一個現有的項目,並且替換數據庫層是不現實的。混合2個DB層只是不好的設計,IMO。 – MacAnthony 2009-11-06 15:00:22

+0

是的,你是對的,我遺漏了mysqli_stmt_fetch($ stmt)行。以前的開發人員使用mysqli-stmt對象而不是結果集對象。如上所述,當我們使用fetch_assoc嘗試結果集時,所有int列都以空字符串形式返回。 – MacAnthony 2009-11-06 15:02:44

+0

這是一個老問題和答案,但mysqli解決方案不再有效......'mysqli_use_result'只會在'mysqli_stmt_execute'後面返回'false' ...'mysqli_use_result'只能在「查詢」後使用, – 2017-11-08 20:19:44

1

它看起來像MySQLi可能只支持通過mysqli_multi_query()多個結果集,因爲MySQLi_STMT對象與MySQLi_Result對象的工作方式不同。

PDO似乎有點抽象,PDOStatement對象能夠處理常規查詢(PDO::query)和預處理語句(PDO:prepare)的多個結果集。

+0

也可以使用'$ stmt-> get_results()'...'$ stmt-> next_result()'來遍歷多個結果集。這兩個函數/方法都只能用於「MySQL Native Driver」 – 2017-11-08 20:21:52

0

這對我來說真的很好,它會處理(作爲例子)儘可能多的選擇列表。注意:您怎麼也得關閉$打電話之前你就可以得到您的SP的OUT參數...

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

而這正是從上面的代碼的輸出看起來像用我test_lists SP ...

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 
相關問題