Mariadb: 使用OFFSET和LIMIT进行分页时跳过了一行

huangapple go评论54阅读模式
英文:

Mariadb: Pagination using OFFSET and LIMIT is skipping one row

问题

我有这个MariaDB表格:

id,名称

id列具有以下属性:主键,自动递增,唯一。

表格有40,000行。

我正在使用PHP和MariaDB从这个表中加载行。这是PHP代码:

$get_rows = $conn->prepare("SELECT * FROM my_table where id > 0 ORDER BY id ASC LIMIT 30 OFFSET ?");
$get_rows->bind_param('i', $offset);
//等等。

第一次查询返回了正确的结果,但在下一次查询(通过AJAX进行),我收到了下一组30行,当前结果和下一组之间有一行的间隙。这种情况一直持续下去。

在表中,第一行已被删除。因此,我恢复了它,现在查询可以正常工作。但是,将来我肯定还会删除更多的行。(我没有软删除的选项)。是否有办法可以继续删除行,并使这些查询返回正确的结果(不跳过任何行)?

编辑

这里是前两次查询中id的范围示例:

查询1:

247--276

查询2:

278--307

(277 缺失)

备注:我询问了ChatGPT,但它无法提供帮助。 :'(

英文:

I have this MariaDB table:

id, name

The id column has these attributes: Primary, auto_increment, unique.

The table has 40,000 rows.

I'm using this PHP & MariaDB to load rows from this table.
This is the PHP code:

$get_rows = $conn->prepare("SELECT * FROM my_table where id> 0 ORDER BY id ASC LIMIT 30 OFFSET ?");
$get_rows->bind_param('i', $offset);
//etc.

The query returned everything correctly at the first time, but in the next query (made through AJAX), I received the next 30 rows with a gap of one row between the current result and the next one. And this goes on and on.

In the table, the row #1 had been deleted. So, I restored it, and now the query works. However, I will definitely have to delete more rows in the future. (I don't have the option of soft-deleting).
Is there any way I can keep deleting rows, and have these queries return correct results (without skipping any row)?

EDIT

Here's an example of the range of the ids in the first 2 queries:

Query 1:

247--276

Query 2:

278--307

(277 is missing)

NB I asked ChatGPT, but it couldn't help. :')

答案1

得分: 1

LIMIT和OFFSET查询是根据位置而不是数值来筛选行。所以如果你删除了第一个“页面”的一行,那么所有后续行的位置都会向下移动一个。

确保不错过行的一种解决方案是通过在前一页的最大id值来定义页面,而不是通过偏移来定义。

$get_rows = $conn->prepare("
  SELECT * FROM my_table where id > ? 
  ORDER BY id ASC LIMIT 30");
$get_rows->bind_param('i', $lastId);

这只适用于您之前的查询浏览了前一页,这样您可以保存该页面上最后一个id的值。

英文:

LIMIT and OFFSET query rows by position, not by value. So if you deleted a row in the first "page," then the position of all subsequent rows moves down by one.

One solution to ensure you don't miss a row is to define pages by the greatest id value on the preceding page, instead of by the offset.

$get_rows = $conn->prepare("
  SELECT * FROM my_table where id> ? 
  ORDER BY id ASC LIMIT 30");
$get_rows->bind_param('i', $lastId);

This only works if your previous query viewed the preceding page, so you can save the value of the last id in that page.

huangapple
  • 本文由 发表于 2023年2月19日 23:04:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75501058.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定