如何通过分页方式高效地显示Oracle数据库中的记录?探索第二种类实现方法!

小贝
预计阅读时长 43 分钟
位置: 首页 小红书 正文

分页显示Oracle数据库记录的类之二

分页显示Oracle数据库记录的类之二

在处理大量数据时,分页显示是一种常见的技术手段,本文将介绍如何使用PHP和OCI(Oracle Call Interface)来实现对Oracle数据库记录的分页显示,通过具体的代码示例和详细解释,帮助开发者理解并实现这一功能。

基本概念

分页原理

分页显示的核心思想是将大量数据分成小块,每次只显示一块数据,从而减少服务器的压力和提高用户体验,分页需要以下几个参数:

当前页码(Current Page): 用户当前查看的页数。

每页显示条数(Items per Page): 每页显示的数据条数。

总记录数(Total Records): 数据库中满足条件的总记录数。

分页显示Oracle数据库记录的类之二

起始记录位置(Start Record Position): 根据当前页码和每页显示条数计算出的起始记录位置。

关键函数

以下是实现分页显示的关键函数:

ReadList(): 读取符合条件的记录,并根据分页参数返回结果。

ThePage(): 显示当前页及总页数。

PrePage(): 生成上一页的链接。

NexPage(): 生成下一页的链接。

NumPage(): 显示分组信息。

分页显示Oracle数据库记录的类之二

具体实现

ReadList函数

function ReadList() {
    $SQL = "SELECT * FROM " . $this->Table . " " . $this->Condition . " ORDER BY " . $this->Id . " DESC";
    $stmt = OCIParse($this->LinkId, $SQL);
    $bool = OCIExecute($stmt);
    
    if (!$bool) {
        echo "连接失败!";
        OCILogoff($this->LinkId);
        exit;
    } else {
        $ncols = OCINumCols($stmt);
        for ($i = 1; $i <= $ncols; $i++) {
            $column_name[$i] = OCIColumnName($stmt, $i);
        }
        
        $k = 0;
        for ($j = 0; $j < $this->StartRec + $this->Offset; $j++) {
            OCIFetch($stmt);
        }
        
        for ($j = 0; $j < $this->MaxLine; $j++) {
            if (OCIFetch($stmt)) {
                $k++;
                for ($i = 1; $i <= $ncols; $i++) {
                    $temp[$column_name[$i]] = OCIResult($stmt, $i);
                }
                $this->Result[] = $temp;
            } else {
                break;
            }
        }
        
        $this->Number = $k;
    }
    OCIFreeStatement($stmt);
    return $this->Result;
}

说明:

OCIParse: 解析SQL语句。

OCIExecute: 执行SQL语句。

OCINumCols: 获取结果集中列的数量。

OCIColumnName: 获取列名。

OCIFetch: 获取一行数据。

OCIResult: 获取指定列的值。

OCIFreeStatement: 释放语句资源。

ThePage函数

function ThePage() {
    echo "第" . $this->CPages . "页/共" . $this->TPages . "页";
}

说明:

显示当前页码和总页数。

PrePage函数

function PrePage($strQuery) {
    $prev = $this->Offset $this->MaxLine;
    if ($prev >= 0) {
        echo "<A href=$PHP_SELF?offset=" . $prev . $strQuery . " class=newslink>上一页</A>";
    } elseif ($this->TheFirstPage != NULL) {
        echo "<A href=" . $this->TheFirstPage . " class=newslink>上一页</A>";
    } else {
        echo "上一页";
    }
}

说明:

计算上一页的偏移量。

如果偏移量大于等于0,则生成上一页的链接。

如果偏移量小于0且存在第一页链接,则使用第一页链接。

否则,仅显示“上一页”。

NexPage函数

function NexPage($strQuery) {
    $next = $this->Offset + $this->MaxLine;
    $k = $this->Total $this->StartRec;
    if ($next < $k) {
        echo "<A href=$PHP_SELF?offset=" . $next . $strQuery . " class=newslink>下一页</A>";
    } else {
        echo "下一页";
    }
}

说明:

计算下一页的偏移量。

如果偏移量小于总记录数减去起始记录数,则生成下一页的链接。

否则,仅显示“下一页”。

NumPage函数

function NumPage() {
    $first = ($this->CGroup 1) * ($this->PGroup) + 1;
    $last = ($first + $this->PGroup > $this->TPages) ? ($this->TPages + 1) : ($first + $this->PGroup);
    $pr = ($this->CGroup 2 >= 0) ? (($this->CGroup 2) * ($this->PGroup) + 1) : (-1);
    $prev = ($pr != -1) ? (($pr 1) * $this->MaxLine) : (0);
    $ne = ($this->CGroup * $this->PGroup + 1 <= $this->TPages) ? ($this->CGroup * $this->PGroup + 1) : (-1);
    $next = ($ne != -1) ? (($ne 1) * $this->MaxLine) : (0);
    
    $k = count($this->PageQuery);
    $strQuery = "";
    //生成一个要传递参数字串
    for ($i = 0; $i < $k; $i++) {
        $strQuery .= "&" . $this->PageQuery[$i][key] . "=" . $this->PageQuery[$i][value];
    }
    
    return array(
        'first' => $first,
        'last' => $last,
        'prev' => $prev,
        'next' => $next,
        'query' => $strQuery,
    );
}

说明:

计算当前分组的第一页和最后一页的起始记录位置。

根据当前分组和每组显示的页数,计算上一组和下一组的起始记录位置。

生成查询字符串,用于传递分页参数。

返回包含上述信息的数组。

示例应用

假设有一个表employees,包含员工的详细信息,我们希望分页显示这些员工的信息,每页显示10条记录,以下是一个完整的示例:

<?php
require 'oci8.inc'; //假设已配置好OCI8库
class Pagination {
    var $Table = 'employees';
    var $Condition = ''; //可以根据需要添加条件,如"WHERE department='Sales'"
    var $Id = 'employee_id'; //主键字段名
    var $StartRec = 0; //起始记录位置
    var $Offset = 0; //偏移量
    var $MaxLine = 10; //每页显示的最大行数
    var $Total = 0; //总记录数
    var $CPages = 1; //当前页码
    var $TPages = 0; //总页数
    var $Result = array(); //存储结果集
    var $TopResult = array(); //存储最新记录的结果集
    var $TopNumber = 0; //最新记录的数量
    var $Number = 0; //当前记录的数量
    var $LinkId; //OCI连接标识符
    var $PageQuery = array(); //存储分页查询参数
    var $TheFirstPage = NULL; //第一页的URL
    var $CGroup = 1; //当前分组号
    var $PGroup = 5; //每组显示的页数
}
$pagination = new Pagination();
$pagination->LinkId = oci_connect('dbname', 'username', 'password'); //连接到数据库
$pagination->CPages = isset($_GET['cp']) ? intval($_GET['cp']) : 1; //获取当前页码参数
$pagination->Offset = ($pagination->CPages 1) * $pagination->MaxLine; //计算偏移量
$pagination->Total = getTotalRecords($pagination->Table, $pagination->Condition); //获取总记录数,假设有这样一个函数
$pagination->TPages = ceil($pagination->Total / $pagination->MaxLine); //计算总页数
$pagination->PageQuery[] = array('key' => 'cp', 'value' => $pagination->CPages); //存储当前页码参数
$pagination->PageQuery[] = array('key' => 'offset', 'value' => $pagination->Offset); //存储偏移量参数
$pagination->PageQuery[] = array('key' => 'maxline', 'value' => $pagination->MaxLine); //存储每页显示行数参数
$pagination->PageQuery[] = array('key' => 'total', 'value' => $pagination->Total); //存储总记录数参数
$pagination->PageQuery[] = array('key' => 'tpages', 'value' => $pagination->TPages); //存储总页数参数
$pagination->PageQuery[] = array('key' => 'table', 'value' => $pagination->Table); //存储表名参数
$pagination->PageQuery[] = array('key' => 'condition', 'value' => $pagination->Condition); //存储条件参数
$pagination->PageQuery[] = array('key' => 'id', 'value' => $pagination->Id); //存储主键字段名参数
$pagination->PageQuery[] = array('key' => 'startrec', 'value' => $pagination->StartRec); //存储起始记录位置参数
$pagination->PageQuery[] = array('key' => 'cpages', 'value' => $pagination->CPages); //存储当前页码参数
$pagination->PageQuery[] = array('key' => 'tpages', 'value' => $pagination->TPages); //存储总页数参数
$pagination->PageQuery[] = array('key' => 'result', 'value' => implode(',', array_keys($pagination->Result))); //存储结果集字段名参数
$pagination->PageQuery[] = array('key' => 'topresult', 'value' => implode(',', array_keys($pagination->TopResult))); //存储最新记录结果集字段名参数
$pagination->PageQuery[] = array('key' => 'topnumber', 'value' => $pagination->TopNumber); //存储最新记录数量参数
$pagination->PageQuery[] = array('key' => 'number', 'value' => $pagination->Number); //存储当前记录数量参数
$pagination->PageQuery[] = array('key' => 'linkid', 'value' => $pagination->LinkId); //存储OCI连接标识符参数
$pagination->PageQuery[] = array('key' => 'pagequery', 'value' => implode('&', array_map(function($item) { return "$item[key]=$item[value]"; }, $pagination->PageQuery))); //存储所有分页查询参数
$pagination->PageQuery[] = array('key' => 'thefirstpage', 'value' => $pagination->TheFirstPage); //存储第一页URL参数
$pagination->PageQuery[] = array('key' => 'cgroup', 'value' => $pagination->CGroup); //存储当前分组号参数
$pagination->PageQuery[] = array('key' => 'pgroup', 'value' => $pagination->PGroup); //存储每组显示页数参数
$pagination->PageQuery[] = array('key' => 'first', 'value' => ($pagination->CGroup 1) * ($pagination->PGroup) + 1); //存储当前分组的第一页起始记录位置参数
$pagination->PageQuery[] = array('key' => 'last', 'value' => ($pagination->CGroup * $pagination->PGroup > $pagination->TPages) ? ($pagination->TPages + 1) : ($pagination->CGroup * $pagination->PGroup)); //存储当前分组的最后一页起始记录位置参数
$pagination->PageQuery[] = array('key' => 'prev', 'value' => ($pagination->CGroup 2 >= 0) ? (($pagination->CGroup 2) * ($pagination->PGroup) + 1) : (-1)); //存储上一组的最后一页起始记录位置参数
$pagination->PageQuery[] = array('key' => 'next', 'value' => ($pagination->CGroup * $pagination->PGroup + 1 <= $pagination->TPages) ? ($pagination->CGroup * $pagination->PGroup + 1) : (-1)); //存储下一组的第一页起始记录位置参数
$pagination->PageQuery[] = array('key' => 'query', 'value' => implode('&', array_map(function($item) { return "$item[key]=$item[value]"; }, $pagination->PageQuery))); //存储所有分页查询参数的字符串形式
?>
<!DOCTYPE html>
<html>
<head>
    <title>分页显示Oracle数据库记录</title>
</head>
<body>
    <h1>员工信息</h1>
    <?php echo $pagination->ThePage(); ?> <br/>
    <?php echo "<table border='1'>"; ?>
    <?php echo "<tr><th>Employee ID</th><th>Name</th><th>Department</th></tr>"; ?>
    <?php while (list($key, $val) = each($pagination->Result)) { ?>
        <tr>
            <td><?php echo htmlspecialchars($val['EMPLOYEE_ID']); ?></td>
            <td><?php echo htmlspecialchars($val['NAME']); ?></td>
            <td><?php echo htmlspecialchars($val['DEPARTMENT']); ?></td>
        </tr>
    <?php } ?>
    <?php echo "</table>"; ?>
    <div>
        <?php echo "<a href='index.php?cp=" . ($pagination->CPages 1) . "&" . implode('&', array_map(function($item) { return "$item[key]=$item[value]"; }, array_filter($pagination->PageQuery, function($item) { return $item['key'] !== 'cp'; }))) . "'>上一页</a> | "; ?>
        <?php echo "<a href='index.php?cp=" . ($pagination->CPages + 1) . "&" . implode('&', array_map(function($item) { return "$item[key]=$item[value]"; }, array_filter($pagination->PageQuery, function($item) { return $item['key'] !== 'cp'; }))) . "'>下一页</a>"; ?>
    </div>
</body>
</html>

说明:

该示例展示了如何使用Pagination类来分页显示employees表中的数据。

Pagination类封装了分页所需的各种方法和属性。

ReadList方法根据分页参数从数据库中读取相应的记录。

ThePage方法显示当前页码和总页数。

PrePageNexPage方法分别生成上一页和下一页的链接。

NumPage方法用于显示分组信息(可选)。

在HTML部分,使用表格展示员工信息,并提供上一页和下一页的导航链接。

常见问题与解答栏目

Q1: 如何优化分页查询以提高性能?

A1: 可以通过以下几种方式优化分页查询的性能:

索引优化: 确保对用于排序和过滤的列建立索引,这可以显著提高查询速度,对于employee_iddepartment等常用查询条件,应创建相应的索引。

覆盖索引: 使用覆盖索引可以减少回表查询的次数,如果查询只需要特定的列,可以在索引中包含这些列,从而避免访问数据表本身,如果经常按departmentemployee_id进行分页查询,可以创建一个组合索引(department, employee_id)

限制返回的数据量: 在可能的情况下,尽量减少查询返回的数据量,如果只需要显示前10条记录,可以在SQL中使用ROWNUM子句来限制结果集的大小,而不是在应用程序层进行限制,这样可以减轻网络传输的负担。

  SELECT * FROM (SELECT a.*, ROWNUM rnum FROM employees a WHERE rownum <= :maxRow) WHERE rnum > :minRow;

分批处理: 如果数据量非常大,可以考虑将数据分成更小的批次进行处理,每次只加载一定数量的记录到内存中,而不是一次性加载所有记录,这样可以减少内存的使用,并且提高响应速度,可以使用游标(Cursor)来逐步读取数据。

  DECLARE @startRow INT;
  DECLARE @endRow INT;
  SET @startRow = 0; --初始值为0,表示从第一条记录开始
  SET @endRow = 10; --每次处理10条记录
  FETCH NEXT FROM employeeCursor INTO @startRow, @endRow; --从游标中获取数据
  WHILE @@FETCH_STATUS = 0 BEGIN
      --处理数据...
      SET @startRow = @startRow + @endRow; --更新起始行号,以便下次循环时从下一批记录开始处理
      SET @endRow = @endRow + 10; --更新结束行号,以便下次循环时从下一批记录结束的位置继续处理
      FETCH NEXT FROM employeeCursor INTO @startRow, @endRow; --再次从游标中获取数据,直到没有更多数据为止。

以上内容就是解答有关“分页显示Oracle数据库记录的类之二”的详细内容了,我相信这篇文章可以为您解决一些疑惑,有任何问题欢迎留言反馈,谢谢阅读。

-- 展开阅读全文 --
头像
如何选择适合的分类信息门户网站模板?
« 上一篇 2024-11-28
如何实现分页显示Oracle数据库记录的类?
下一篇 » 2024-11-28

相关文章

取消
微信二维码
支付宝二维码

发表评论

暂无评论,1人围观

头像 蒋芳 说道:
2024-08-30 · Google Chrome 78.0.3904.108 Huawei JEF

企业要提升客户忠诚度和销售效率,关键在于深耕私域流量,通过精准服务和个性化互动,让客户成为品牌的忠实拥趸。

目录[+]