2

我只是尝试使用 Oracle 数据库,发现分页有问题。上次我在 MySQL 中使用它工作得很好。

查看我的代码:

<?php
$page = $_POST['page'];
$cur_page = $page;
$page -= 1;
$per_page = 3;
$previous_btn = true;
$next_btn = true;
$first_btn = true;
$last_btn = true;
$start = $page * $per_page;

$query_pag_data = "SELECT P.FORM_NO, P.MODEL_NO, P.PRODUCTION_STATUS, P.REMARKS, P.DATE_ADDED, P.TIME, P.QTY_PLAN, M.MODEL_NO, M.MODEL_NAME
                    FROM SEIAPPS_PRODUCTION_STATUS P, SEIAPPS_MODEL M
                    WHERE ROWNUM BETWEEN $start AND $per_page AND P.MODEL_NO = M.MODEL_NO ORDER BY P.DATE_ADDED DESC, P.TIME";

$result_pag_data = oci_parse($c1, $query_pag_data);
oci_execute($result_pag_data);

我用过 ROWNUM,但是当我想打开第 2 页或下一页时,它没有显示任何数据。而表中仍有更多数据。

有谁请帮忙指点一下。谢谢

4

1 回答 1

2

ROWNUM在 Oracle 中不像LIMIT在 MySQL 中。

MySQL中,

LIMIT子句可用于约束SELECT语句返回的行数... 有两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为 0(不是 1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

甲骨文中,

对于查询返回的每一行,ROWNUM伪列返回一个数字,指示 Oracle 从表或连接行集中选择行的顺序。选择的第一行的 aROWNUM为 1,第二行的 a 为 2,依此类推。

SELECT *
  FROM (SELECT * FROM employees ORDER BY employee_id)
  WHERE ROWNUM < 11;

在前面的示例中,这些ROWNUM值是顶级SELECT语句的值,因此它们是在子查询中已经按employee_id 对行进行排序之后生成的。

所以你的代码的问题是:

  • WHERE ROWNUM BETWEEN :startrow AND :perpage逻辑上不正确,因为ROWNUM是行索引指示符,而不是“行数”指示符。ROWNUM BETWEEN a AND b表示返回从 a 到 b 排序的行,例如第 1 行到第 3 行,而不是第 1 行和第 3 行。

    因此,即使ROWNUM BETWEEN a AND b有效(实际上没有),从逻辑上讲,要获取查询的“第 2 页” ROWNUM BETWEEN :startrow AND :endrow,例如ROWNUM BETWEEN 4 AND 6

  • ROWNUM BETWEEN :startrow AND :endrow实际上不适用于大于 1 的起始行,因为它是一个伪列,表示所选集中ROWNUM行的顺序,

    所以当你执行例如SELECT...WHERE ROWNUM BETWEEN 4 AND 6

    • 第一场比赛,Oracle 想,“rownum 会在 4 到 6 之间吗?” 因为还没有选中行,所以选中ROWNUM后为1 ,所以Oracle放弃;
    • 第二场比赛,“这会是 4 比 6 吗?” 否,因为没有选择任何行,所以这仍然是 1;
    • 第三场比赛,相同;
    • ...

    根本不会有结果。

    要获得所需的输出,您必须将查询包装在子查询中,并检查外部的行号,如下所示:

SELECT * FROM
  (SELECT ROWNUM rn, t.*
    FROM
      (SELECT ...
        FROM ...
        WHERE ...
        ORDER BY ...) t
  )
  WHERE rn>=:startrow AND rn<=:endrow

以保证在检查行顺序之前确定行顺序。

  • 关于编码风格,由于 OCI 支持预处理语句变量绑定,你应该使用它:

    绑定允许数据库重用语句上下文和先前执行语句的缓存,...绑定减少了 SQL 注入问题,因为与绑定变量关联的数据永远不会被视为 SQL 语句的一部分。

$statement=oci_parse("... WHERE rn>=:start AND rn<=:end");
oci_bind_by_name($statement,":start",$start,-1,SQLT_INT);
oci_bind_by_name($statement,":end",intval($start+$per_page-1),-1,SQLT_INT);
oci_execute($statement);
于 2013-09-24T09:10:42.117 回答