data_seek
Erfahren Sie, wie mysqli_data_seek() in PHP den Ergebniszeiger auf eine beliebige Zeile eines gepufferten Ergebnisses verschiebt.
Die Funktion mysqli_data_seek() in PHP verschiebt den internen Ergebniszeiger auf eine beliebige Zeile in einem gepufferten Ergebnissatz. Der nächste Abrufaufruf liest dann aus dieser Zeile statt aus der nächsten sequenziellen. Sie können damit direkt zu einer Zeile springen, bereits übersprungene Zeilen erneut lesen oder von vorne beginnen, ohne die Abfrage erneut auszuführen. Zeilenindizes sind nullbasiert, und die Funktion gibt bei Erfolg true oder bei Misserfolg false zurück.
Dieses Kapitel behandelt die Funktionssignatur, den prozeduralen und den objektorientierten Stil, ein ausführbares Beispiel, die Anforderung an gepufferte Ergebnisse, die häufig zu Problemen führt, sowie den Zeitpunkt, wann SQL LIMIT … OFFSET das bessere Werkzeug ist.
Syntax
// Procedural style
mysqli_data_seek(mysqli_result $result, int $offset): bool
// Object-oriented style
$result->data_seek(int $offset): bool$result— ein Ergebnissatz, der vonmysqli_query(),mysqli_store_result()odermysqli_use_result()zurückgegeben wird.$offset— die Zeilennummer, zu der gesprungen werden soll, beginnend bei0für die erste Zeile. Der Wert muss zwischen0undmysqli_num_rows() - 1liegen.- Rückgabewert —
true, wenn der Sprung erfolgreich war,false, wenn der Offset außerhalb des gültigen Bereichs liegt oder der Ergebnissatz ungepuffert ist.
Die Anforderung an gepufferte Ergebnisse
mysqli_data_seek() funktioniert nur bei gepufferten Ergebnissätzen — solchen, deren Zeilen bereits im Speicher gehalten werden. Das ist das, was Sie von mysqli_query() erhalten (das intern mysqli_store_result() aufruft) und direkt von mysqli_store_result().
Wenn Sie Zeilen lazy mit mysqli_use_result() abrufen, werden die Zeilen einzeln vom Server gestreamt und es gibt nichts, in dem gesucht werden könnte. mysqli_data_seek() schlägt dann fehl. Wenn Sie wahlfreien Zugriff benötigen, verwenden Sie einen gepufferten Ergebnissatz.
Verwendung von mysqli_data_seek()
Rufen Sie die Funktion mit einem gültigen Ergebnissatz auf und übergeben Sie den gewünschten Zeilenindex. Der nächste Abruf gibt dann diese Zeile zurück:
<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");
$result = mysqli_query($mysqli, "SELECT id, name FROM users ORDER BY id");
if (!$result) {
echo "Failed to execute query: " . mysqli_error($mysqli);
exit();
}
// Move the pointer to row 3 (index 2, because indices are zero-based)
if (!mysqli_data_seek($result, 2)) {
echo "Seek failed";
exit();
}
// Fetch the row the pointer now points at
$row = mysqli_fetch_assoc($result);
print_r($row);
mysqli_free_result($result);
mysqli_close($mysqli);
?>Wir stellen die Verbindung mit mysqli_connect() her, führen die Abfrage mit mysqli_query() aus und prüfen auf Fehler. Dann springt mysqli_data_seek($result, 2) den Zeiger auf die dritte Zeile, und mysqli_fetch_assoc() liest sie aus. Das Prüfen des Rückgabewerts von mysqli_data_seek() ermöglicht eine saubere Behandlung eines außerhalb des Bereichs liegenden Offsets.
Einen Ergebnissatz von Anfang an erneut lesen
Ein gängiger, datenbankfreier Weg, das Verhalten des Zeigers genau zu beobachten, besteht darin, einen Ergebnissatz zu durchlaufen, dann zurück zu 0 zu springen und ihn erneut zu durchlaufen. Dieses Snippet verwendet ein einfaches PHP-array, um dieselbe Abruf-und-Sprung-Logik ohne einen laufenden MySQL-Server zu modellieren:
<?php
// A result set modelled as an in-memory array of rows.
$rows = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
['id' => 3, 'name' => 'Carol'],
];
$pointer = 0;
// "data_seek": move the pointer to an arbitrary index, like mysqli_data_seek().
function data_seek(array $rows, int $offset, int &$pointer): bool
{
if ($offset < 0 || $offset >= count($rows)) {
return false;
}
$pointer = $offset;
return true;
}
// First pass: read every row sequentially.
echo "First pass:\n";
while ($pointer < count($rows)) {
echo $rows[$pointer]['name'] . "\n";
$pointer++;
}
// Rewind to the top and read again.
data_seek($rows, 0, $pointer);
echo "Second pass (after seek to 0):\n";
echo $rows[$pointer]['name'] . "\n"; // Alice again
?>Die Ausgabe lautet:
First pass:
Alice
Bob
Carol
Second pass (after seek to 0):
AliceBei einem echten mysqli_result würden Sie die array-Logik durch mysqli_data_seek($result, 0) gefolgt von mysqli_fetch_assoc($result) ersetzen, um einen gepufferten Ergebnissatz zurückzuspulen, ohne die Abfrage erneut auszuführen.
Wann LIMIT/OFFSET die bessere Wahl ist
mysqli_data_seek() dient der Navigation in einem Ergebnissatz, den Sie bereits heruntergeladen haben. Wenn Ihr Ziel darin besteht, nur einen Ausschnitt einer großen Tabelle abzurufen, sollten Sie nicht alle Zeilen in PHP laden, um darin zu suchen — delegieren Sie die Arbeit mit LIMIT und OFFSET an die Datenbank:
SELECT id, name FROM users ORDER BY id LIMIT 10 OFFSET 20;Damit werden nur die 10 gewünschten Zeilen zurückgegeben, was Speicher und Netzwerkverkehr spart. Verwenden Sie mysqli_data_seek() für Fälle, in denen Sie wirklich wahlfreien Zugriff auf einen Ergebnissatz benötigen, der sich bereits im Speicher befindet — etwa wenn Sie innerhalb einer einzelnen Anfrage frühere Zeilen erneut lesen müssen.
Fazit
mysqli_data_seek() positioniert den internen Zeiger eines gepufferten Ergebnissatzes neu, sodass Sie zu jeder nullbasierten Zeile springen können, auch zurück zum Anfang. Beachten Sie die zwei Einschränkungen: Der Offset muss im gültigen Bereich liegen (0 … num_rows - 1), und der Ergebnissatz muss gepuffert sein. Zum Einschränken großer Datensätze bevorzugen Sie SQL LIMIT/OFFSET; für das Navigieren in Daten, die sich bereits im Speicher befinden, ist mysqli_data_seek() das richtige Werkzeug.
Verwandte Funktionen: mysqli_fetch_assoc(), mysqli_fetch_array(), mysqli_fetch_row() und mysqli_query().