【问题标题】:Oracle SQL query returns same set of results despite variation in ROWNUM value尽管 ROWNUM 值不同,Oracle SQL 查询仍返回相同的结果集
【发布时间】:2015-01-06 19:06:36
【问题描述】:

我正在开发一个 Oracle/PHP 应用程序并尝试实现“加载更多”功能。

这是两个表及其结构:

questions: id (int) | title (varchar(999)) | datetime (varchar(999))

questions_tags: id (int) | question_id (int) | tag_id (int)

以下是index.php中的代码:

$stid = oci_parse($conn, "select * from (
                              select a.*, ROWNUM rnum from (
                                  SELECT questions.id FROM questions_tags, questions WHERE 
                                      questions.id = questions_tags.question_id AND
                                      questions_tags.tag_id IN (1,2,3,4,5,6,7) ORDER BY questions.datetime ASC
                              ) a where rownum <= 10
                          ) where rnum >= 0");
oci_execute($stid);
while (oci_fetch($stid)) {
    // Do work with the results
}

下面是它背后的javascript:

$("#load_more").click(function(e) {
    $.ajax({
        url: "loadMore.php?x=" + $(".span_data:last").data("id"),
        success:function(data, textStatus, jqXHR)
        {
            if (data)
            {
                // append data
            } else {
                // remove button
            }
        },
        error: function(jqXHR, textStatus, errorThrown)
        {
            //if fails
        }
    });
    e.preventDefault(); //STOP default action
});

最后,这里是 loadMore.php 文件:

<?php
$x = $_GET['x'];
$xTen = intval($x) + 10;
$count_id = $x;

try
{
    $lastID = 0;
    $tagIDs = implode("','", $user_tag_ids);
    $stid = oci_parse($conn, "select * from (
                                  select a.*, ROWNUM rnum from (
                                      SELECT questions.id FROM questions_tags, questions WHERE
                                          questions.id = questions_tags.question_id AND
                                          questions_tags.tag_id IN (1,2,3,4,5,6,7) ORDER by questions.datetime DESC
                              ) a where rownum <= $xTen
                          ) where rnum >= $x");
    oci_execute($stid);
    while (oci_fetch($stid)) {
        // Do work with the results
    }
}
catch(Exception $e) {
    print "Error";
}
?>

无论x 的值是多少,loadMore.php 文件都会继续返回相同的结果集。因此,如果我执行/loadMore.php?x=10,我将得到与/loadMore.php?x=100 返回的结果相同的结果。但是,如果我走得更远(/loadMore.php?x=1500),那是我最终得到不同结果的时候。我不明白这里出了什么问题。

正如我在 cmets 中所说的:

如果我删除所有rownum 参数并运行

SELECT * FROM questions WHERE EXISTS (
    SELECT 1 FROM questions_tags WHERE 
        questions.id = questions_tags.question_id AND 
        questions_tags.tag_id IN (1,2,3,4,5,6,7)
) ORDER BY datetime DESC

我得到了所有结果,可能有一千行。我试图获取这千行中的前 10 行,然后当用户单击“加载更多”按钮时继续获取下 10 行。这就是为什么我有相同的查询 index.php 和 loadMore.php

【问题讨论】:

  • questions.datetime 是唯一的吗?如果您的ORDER BY 没有生成唯一的订单,那么即使使用相同的参数,一行也完全有可能在后续执行中得到不同的ROWNUM。换句话说,如果“前 10 个”没有明确定义,因为有数百行具有相同的 datetime 值,那么您的方法将无法正常工作。
  • datetime 不是唯一的。如果我删除所有 rownum 参数并只运行 SELECT * FROM questions WHERE EXISTS (SELECT 1 FROM questions_tags WHERE questions.id = questions_tags.question_id AND questions_tags.tag_id IN ('$tagIDs'))ORDER BY datetime DESC 查询,我会得到所有结果,可能有一千行。我非常想做的是获取这千行中的前 10 行,然后在用户单击“加载更多”按钮时继续获取下 10 行。这就是为什么我有相同的查询 index.phploadMore.php
  • 如果您想要一个可以依赖的排序,那么您需要在 ORDER BY 子句中包含足够多的列,以便所有这些列的组合对于每一行都是唯一的。没有其他保证。
  • 您可能会摆脱最外层的查询,并在第一个内部查询中使用WHERE rownum BETWEEN $x and $xTen 之类的内容。另外,sql注入警告。加 10 时你 intval $x ,但在获得初始值时不是。最后,这将返回 11 行,而不是 10 行。您可能希望从 $xTen 中减去 1 或将 &lt;= $xTen 切换为 &lt; $xTen。将&gt;= 留在$x 比较中。
  • 只是阅读,我看到你正在做的方式应该是最佳解决方案。我整天都在使用 Oracle,但有一段时间不用在其中进行分页了,因为我们通常没有大型列表。

标签: php sql oracle


【解决方案1】:

感谢 cmets,我意识到 ORDER BY questions.datetime 不够独特,无法正确排序结果。将查询更改为 ORDER BY questions.datetime DESC, questions.id DESC 解决了问题并开始显示独特的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    相关资源
    最近更新 更多