PHP Oracle Pagination Cant使用ROWNUM显示数据

时间:2013-09-24 07:25:10

标签: php oracle pagination

我只是尝试使用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页或下一页时,它没有显示任何数据。而表中仍有更多数据。

任何人都可以提供建议。 感谢

1 个答案:

答案 0 :(得分:2)

Oracle中的

ROWNUM与MySQL中的LIMIT不同。

MySQL

  

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

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

Oracle

  

对于查询返回的每一行,ROWNUM伪列返回一个数字,表示Oracle从一个表或一组连接的行中选择行的顺序。选中的第一行的ROWNUM为1,第二行为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

    • 第一场比赛,甲骨文认为,“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支持prepared statementvariable binding,您应该使用它:

      

    Binding允许数据库重用声明上下文和语句的先前执行中的缓存,... Binding减少了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);