W3docs

data_seek

In this article, we will focus on the mysqli_data_seek() function in PHP, which is used to move the result pointer to a specified row number in a result set. We

The mysqli_data_seek() function in PHP moves the internal result pointer to an arbitrary row in a buffered result set, so the next fetch call reads from that row instead of the next sequential one. It lets you jump directly to a row, re-read rows you have already passed, or restart from the beginning without running the query again. Row indices are zero-based, and the function returns true on success or false on failure.

This chapter covers the function signature, both the procedural and object-oriented styles, a runnable example, the buffered-result requirement that trips most people up, and when a SQL LIMIT … OFFSET is the better tool.

Syntax

// Procedural style
mysqli_data_seek(mysqli_result $result, int $offset): bool

// Object-oriented style
$result->data_seek(int $offset): bool
  • $result — a result set returned by mysqli_query(), mysqli_store_result(), or mysqli_use_result().
  • $offset — the row number to move to, starting at 0 for the first row. It must be between 0 and mysqli_num_rows() - 1.
  • Return valuetrue if the seek succeeds, false if the offset is out of range or the result set is unbuffered.

The buffered-result requirement

mysqli_data_seek() only works on buffered result sets — ones whose rows are already held in memory. That is what you get from mysqli_query() (which calls mysqli_store_result() internally) and from mysqli_store_result() directly.

If you fetch rows lazily with mysqli_use_result(), the rows stream from the server one at a time and there is nothing to seek into, so mysqli_data_seek() will fail. When you need random access, stick with a buffered result.

How to use mysqli_data_seek()

Call the function on a valid result set and pass the row index you want to land on. The next fetch then returns that row:

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

We connect with mysqli_connect(), run the query with mysqli_query(), and check for errors. Then mysqli_data_seek($result, 2) jumps the pointer to the third row, and mysqli_fetch_assoc() reads it. Checking the return value of mysqli_data_seek() lets you handle an out-of-range offset cleanly.

Re-reading a result set from the start

A common, database-free way to see exactly how the pointer behaves is to walk a result, then seek back to 0 and walk it again. This snippet uses a plain PHP array to model the same fetch-then-seek logic without needing a live MySQL server:

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

This prints:

First pass:
Alice
Bob
Carol
Second pass (after seek to 0):
Alice

With a real mysqli_result, you would replace the array logic with mysqli_data_seek($result, 0) followed by mysqli_fetch_assoc($result) to rewind a buffered result without re-running the query.

When to use LIMIT/OFFSET instead

mysqli_data_seek() is for navigating a result set you have already downloaded. If your goal is to fetch only a slice of a large table, do not pull every row into PHP just to seek — push the work to the database with LIMIT and OFFSET:

SELECT id, name FROM users ORDER BY id LIMIT 10 OFFSET 20;

This returns only the 10 rows you want, saving memory and network traffic. Reserve mysqli_data_seek() for cases where you genuinely need random access across a result set that is already in memory — for example, re-reading earlier rows during a single request.

Conclusion

mysqli_data_seek() repositions the internal pointer of a buffered result set so you can jump to any zero-based row, including back to the start. Remember its two constraints: the offset must be in range (0num_rows - 1), and the result must be buffered. For trimming large datasets, prefer SQL LIMIT/OFFSET; for moving around data already in memory, mysqli_data_seek() is the right tool.

Related functions: mysqli_fetch_assoc(), mysqli_fetch_array(), mysqli_fetch_row(), and mysqli_query().

Practice

Practice
What is the primary function of the PHP method mysql_data_seek()?
What is the primary function of the PHP method mysql_data_seek()?
Was this page helpful?