【问题标题】:How paginate a specific query?如何对特定查询进行分页?
【发布时间】:2012-12-31 15:17:02
【问题描述】:

即使是互联网上的“简单”分页教程,我也很难理解。

我正在为我的公司创建一个 Intranet 站点,完成它的唯一步骤是对所有查询进行分页,因为它们都包含数千个结果,尤其是搜索结果。

我的问题是我能否按如下方式对查询进行分页:

SELECT * FROM hdticket WHERE id = 22;

【问题讨论】:

  • Please, don't use mysql_* functions in new code。它们不再维护and are officially deprecated。看到red box?改为了解prepared statements,并使用PDOMySQLi - this article 将帮助您决定哪个。如果你选择 PDO,here is a good tutorial.
  • 让我成为许多人中的第一个:永远不要将$_GET['anything'] 直接放入您的查询中。这是灾难的秘诀。谷歌“SQL 注入”以了解原因。
  • 好分页意味着使用 LIMIT 子句获取数据,我在您的查询中没有看到...根据您的样式问题,您可以做表格或 css 或任何您喜欢的东西
  • 为了不让事情变得比它需要的更复杂,我删除了与 PHP 相关的所有内容,因为它开始的简单方式是仅使用 SQL。我希望这是针对您的需求。还要仔细检查你的 mysql 使用情况,我强烈建议你改用比 mysql_* 函数更容易使用的东西。请看stackoverflow.com/a/11580420/367456

标签: mysql pagination


【解决方案1】:

您需要在 MySQL 查询中添加 LIMIT 子句。这很简单:

SELECT * FROM hdticket WHERE id = :ticknum LIMIT 0, 10

这将从头开始获取 10 条记录(假设您的记录是基于零索引的)。第一个数字是从何时开始提取,第二个数字是之后要提取的数量。所以从 0 开始,它正在获取接下来的 10 条记录。这将是第 1 页。

要获得后续的记录页,您只需要增加第一个数字。因此,要获取第二页,您需要从 10 开始计数,并获取接下来的 10 条记录。这个查询看起来像这样:

SELECT * FROM hdticket WHERE id = :ticknum LIMIT 10, 10

然后是第 3 页:

SELECT * FROM hdticket WHERE id = :ticknum LIMIT 20, 10

等等。希望您能看到正在出现的模式。

当您使用$_GET 参数时,您可以定制您的网址来分页您的记录。所以 http://intranet/index.php?page=2 的 URL 会给出:

<?php

$page = intval($_GET['page']);
$limit = 10;
$offset = (($page - 1) * $limit);

$sql = "SELECT * FROM hdticket WHERE id = :ticknum LIMIT $offset, $limit";

希望这会有所帮助。

另外,还有几句旁白。不要使用 mysql_ 函数,因为它们已被弃用。您可以从官方手册页中看到这一点:http://php.net/manual/en/function.mysql-query.php

此外,您的代码容易受到 SQL 注入攻击,因为您正在获取 URL 中的内容并直接在 SQL 查询中使用它。如果您在其中输入用于分页的数字,这一切都很好,但是如果有人恶意将 SQL 放入 URL,他们可以做各种各样的事情,例如截断您的表或整个数据库,这会发生,因为您'只是通过它而不检查它。

为了解决这个问题,如果您使用 mysql_ 函数的替代方法,例如 PDO,您可以在 SQL 语句中准备变量。您的代码将如下所示:

<?php

$sql = "SELECT * FROM hdticket WHERE id = :ticknum LIMIT :offset, :limit";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':ticknum', $ticknum, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();

这可以确保传递给您的 SQL 字符串的数据是您所期望的,并自动转义以防止 SQL 注入。

【讨论】:

  • 同意你需要 LIMIT 来做服务器端分页。但是,如果您使用 LIMIT,则应始终包含 ORDER BY 子句。这将确保每次以相同的顺序返回行,这是一致分页所必需的。实际上,无论如何,MySQL 可能会以一致的顺序返回行,但最好不要依赖它。
  • @jfrank 借调。本来打算记下这一点,但忘记了自己警告 SQL 注入漏洞!
  • 感谢 Martin 和所有做出贡献的人!这完美地回答了我的问题!我知道不推荐使用的 mysql_ 函数,尽管我一次一步地学习 OOP,尽管我在非常年轻的时候就开始了这个。此外,由于这是一个内部站点,我正在为安全网络上的计算机文盲开发,我不太担心注入,尽管我一定会在未来的项目中记住这一点!谢谢大家!
  • 我仍然会解决注入漏洞。这是一个好习惯,你永远不知道会访问你的代码。仅仅因为今天计算机文盲的人正在访问并不意味着明天一个好奇的 16 岁实习生会被放任自流并杀死您的数据库。
【解决方案2】:

你可以使用 top / limit 来做到这一点..

如果你只想要前 10 名,那么:

  select top 10,* from table;

或 如果你想去页面那么:

  select * from table limit 10 , 20;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 2019-12-23
    • 2012-08-19
    • 1970-01-01
    • 2015-08-20
    • 2012-06-30
    • 2017-09-15
    相关资源
    最近更新 更多