我有一个包含多个结果集的存储过程。如何进入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,但由于某种原因,所有的int都以空字符串形式返回。
还有其他人遇到过此问题吗?
答案 0 :(得分:14)
我认为你在这里遗漏了一些东西(以下内容尚未经过测试):
$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
将使您的代码看起来更具吸引力(我的个人观点)。
答案 1 :(得分:1)
看起来MySQLi可能只支持mysqli_multi_query()
的多个结果集,因为MySQLi_STMT
个对象与MySQLi_Result
个对象的工作方式不同。
PDO似乎有点抽象,PDOStatement对象能够为常规查询(PDO::query
)和预处理语句(PDO:prepare
)处理多个结果集。
答案 2 :(得分:1)
这对我来说非常有用,它会处理(作为一个例子)你的SP中有很多选择列表。注意你必须先关闭$ call,然后才能从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