分页显示Oracle数据库记录的类之二
在处理大量数据时,分页显示是一种常见的技术手段,本文将介绍如何使用PHP和OCI(Oracle Call Interface)来实现对Oracle数据库记录的分页显示,通过具体的代码示例和详细解释,帮助开发者理解并实现这一功能。
基本概念
分页原理
分页显示的核心思想是将大量数据分成小块,每次只显示一块数据,从而减少服务器的压力和提高用户体验,分页需要以下几个参数:
当前页码(Current Page): 用户当前查看的页数。
每页显示条数(Items per Page): 每页显示的数据条数。
总记录数(Total Records): 数据库中满足条件的总记录数。
起始记录位置(Start Record Position): 根据当前页码和每页显示条数计算出的起始记录位置。
关键函数
以下是实现分页显示的关键函数:
ReadList(): 读取符合条件的记录,并根据分页参数返回结果。
ThePage(): 显示当前页及总页数。
PrePage(): 生成上一页的链接。
NexPage(): 生成下一页的链接。
NumPage(): 显示分组信息。
具体实现
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
方法显示当前页码和总页数。
PrePage
和NexPage
方法分别生成上一页和下一页的链接。
NumPage
方法用于显示分组信息(可选)。
在HTML部分,使用表格展示员工信息,并提供上一页和下一页的导航链接。
常见问题与解答栏目
Q1: 如何优化分页查询以提高性能?
A1: 可以通过以下几种方式优化分页查询的性能:
索引优化: 确保对用于排序和过滤的列建立索引,这可以显著提高查询速度,对于employee_id
和department
等常用查询条件,应创建相应的索引。
覆盖索引: 使用覆盖索引可以减少回表查询的次数,如果查询只需要特定的列,可以在索引中包含这些列,从而避免访问数据表本身,如果经常按department
和employee_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数据库记录的类之二”的详细内容了,我相信这篇文章可以为您解决一些疑惑,有任何问题欢迎留言反馈,谢谢阅读。
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/685445.html