Abrufen mehrerer Resultsets mit Stored Procedure in php / mysqli
-
18-09-2019 - |
Frage
Ich habe eine gespeicherte Prozedur, die mehrere Ergebnismengen hat. Wie komme ich zum zweiten Ergebnismenge in mysqli vorrücken, um diese Ergebnisse zu erhalten?
Lassen Sie uns sagen, es ist eine gespeicherte Prozedur wie:
create procedure multiples( param1 INT, param2 INT )
BEGIN
SELECT * FROM table1 WHERE id = param1;
SELECT * FROM table2 WHERE id = param2;
END $$
Die PHP ist so etwas wie folgt aus:
$stmt = mysqli_prepare($db, 'CALL multiples(?, ?)');
mysqli_stmt_bind_param( $stmt, 'ii', $param1, $param2 );
mysqli_stmt_execute( $stmt );
mysqli_stmt_bind_result( $stmt, $id );
Dann ist dies der Teil kann ich nicht an der Arbeit. Ich habe versucht, mysqli_next_result mit auf die nächste Ergebnismenge zu bewegen, aber nicht bekommen kann, damit es funktioniert. Wir haben es mit mysqli_store_result und mysqli_fetch_assoc / array / Zeile, aber aus irgendeinem Grunde all ints erhalten zurückgegeben als leere Strings zu arbeiten.
Jeder sonst über diese kommen und eine Lösung?
Lösung
Ich glaube, Sie etwas hier sind vermisst (Folgendes wurde nicht geprüft):
$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);
Mit PDO
Ihr Code würde wie folgt aussehen:
$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']);
}
Aber ich habe gehört, dass der PDOStatement::nextRowset()
nicht mit der Umsetzung MySQL PDO Treiber es unmöglich macht, mehrere Ergebnisse zu erhalten:
- PDO nextRowset nicht auf MySQL arbeiten
- pdo_mysql: Stored Procedure Call einzelne rowset Blöcke zukünftige Abfragen Rückkehr
- können nicht gespeicherte Prozeduren von PDO auf Windows verwenden
Also, je nach PHP-Version, dann würden Sie mit Ihrem halten müssen mysqli
-Lösung. Durch die Art und Weise: Verwenden Sie den prozeduralen Stil bewusst? Mit objektorientiertem Stil mit mysqli
würde Ihren Code aussieht eine wenig ansprechende (meine persönliche Meinung) machen.
Andere Tipps
Das hat wirklich gut für mich gearbeitet hat, wird es mit (als Beispiel), so viele Select-Listen umgehen, wie es in Ihrem SP ist. Beachten Sie, wie Sie den $ Anruf zu schließen, bevor Sie dann zu den OUT-Parametern von Ihrem SP bekommen ...
?><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><?
Und das ist, was die Ausgabe des obigen Code sieht meinen test_lists wie mit 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
Es sieht aus wie MySQLi nur mehrere Ergebnismengen durch mysqli_multi_query()
unterstützen können, da MySQLi_STMT
Objekte anders MySQLi_Result
Objekten arbeiten.
PDO scheint etwas abstrahiert zu sein, mit dem PDOStatement Objekte in der Lage, mehrere Ergebnisse für beide regelmäßige Abfragen (PDO::query
) und Prepared Statements (PDO:prepare
).