关于分页算法的详细说明

这种model1模式页面显示和分页的业务逻辑混合在一起.比较简单.

但是代码可读性很差,而且不容易维护.

 

在韩顺平SERVLET教程的第四讲中有明确的说明.

晚上弄清楚算法,贴过来.

 

需要4个参数

pageSize --> 用户指定

pageNow --> 用户选择

rowCount --> 从表中查询出来

pageCount --> 计算出来

 

pageCount的计算方法

if (rowCount % pageSize == 0) {

    pageCount = rowCount / pageSize;

}else {

    pageCOunt = rowCount / pageSize + 1;

}

 

说明:如果用户的表中有9条记录,即rowCount =  9,pageSize = 3的话,那么pageCount就为3,正确

        如果pageSize = 4,rowCount / pageSize取整也是2,+1后共3页.正确.

 

针对上面的算法,很自然的想到下面的SQL语句

select 字段表名 from 表名 where id bwteen ? and ?

比如显示第三页(pageSize = 3)的话,那么就是

select * from user where userId bwteen 7 and 9;

但是有这样一个问题,如果userId被删除掉或者不连续的话,那么返回的结果集就是错误的.

 

下面列出常见的几个数据库的分页SQL语句

MySQL数据库

My sql数据库最简单,是利用mysql的LIMIT函数,LIMIT [offset,] rows

从数据库表中M条记录开始检索N条记录的语句为:

  SELECT * FROM 表名称 LIMIT M,N

  例如从表Sys_option(主键为sys_id)中从10条记录还是检索20条记录,语句如下:

  select * from sys_option limit 10,20

例如要从"品种"表里检索,语句为

sql = "select * from pinzhong limit "+pageSize+","+pageSize*(pageNow-1)+"  " ;

 

在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能。

SELECT   *   FROM   table   LIMIT  [ offset, ]  rows  |  rows OFFSET offset


LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1): 为了与 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。

mysql >   SELECT   *   FROM   table  LIMIT  5 , 10 ;   //  检索记录行  6 - 15

// 为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为  - 1 : 
mysql
>   SELECT   *   FROM   table  LIMIT  95 , - 1 //  检索记录行  96 - last.

// 如果只给定一个参数,它表示返回最大的记录行数目: 
mysql
>   SELECT   *   FROM   table  LIMIT  5 ;      // 检索前  5  个记录行

// 换句话说,LIMIT n 等价于 LIMIT  0 ,n。

 

SQL Server

  从数据库表中的第M条记录开始取N条记录,利用Top关键字:注意如果Select语句中既有top,又有order by,则是从排序好的结果集中选择:

  SELECT*
  FROM(SELECTTopN*
  FROM(SELECTTop(M+N-1)*FROM表名称Orderby主键desc)t1)t2
  Orderby主键asc

  例如从表Sys_option(主键为sys_id)中从10条记录还是检索20条记录,语句如下:

  SELECT*
  FROM(SELECTTOP20*
  FROM(SELECTTOP29*FROMSys_optionorderbysys_iddesc)t1)t2
  Orderbysys_idasc

  Oralce数据库

  从数据库表中第M条记录开始检索N条记录

  SELECT*
  FROM(SELECTROWNUMr,t1.*From表名称t1whererownum<M+N)t2
  wheret2.r>=M

  例如从表Sys_option(主键为sys_id)中从10条记录还是检索20条记录,语句如下:

  SELECT*
  FROM(SELECTROWNUMR,t1.*FromSys_optionwhererownum<30)t2
  Wheret2.R>=10

 

 

在mysql数据库中分页实例

		response.setContentType("text/html;charset=gbk") ;
		request.setCharacterEncoding("gbk") ;

		PrintWriter pw = response.getWriter() ;

		//定义连接数据库所需要的几个常量
		final String DBDriver = "com.mysql.jdbc.Driver";
		final String DBURL = "jdbc:mysql://localhost:3306/test";
		final String user = "";
		final String password = "";
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;

		

		try {
			//定义分页所需要的几个变量
			int pageCount = 0;
			int pageSize = 3;
			int rowCount = 0;
			int pageNow = 1;
			
			//动态的接收pageNow,实现分页的实时功能
			String spageNow = request.getParameter("pageNow") ;
			
			if(spageNow != null) {
				pageNow = Integer.parseInt(spageNow) ;
			}

			Class.forName(DBDriver).newInstance();
			conn = DriverManager.getConnection(DBURL, user, password);

			String sql_count = "select count(*) from pinzhong"; //取得当前表中总的记录数

			ps = conn.prepareStatement(sql_count);
			rs = ps.executeQuery();

			//取得rowCount
			if (rs.next()) {
				rowCount = rs.getInt(1);
			}

			//计算pageCount 
			if ((rowCount % pageSize) == 0) {
				pageCount = rowCount / pageSize;
			} else {
				pageCount = rowCount / pageSize + 1;
			}

			System.out.println("pageSize->" + pageSize) ;
			System.out.println("pageCount->" + pageCount) ;
			System.out.println("pageSize*(pageNow-1)->" + pageSize*(pageNow-1)) ;
			System.out.println("spageNow->" + spageNow) ;
			
			String sql_do = "select * from pinzhong limit "+pageSize*(pageNow-1)+" , "+pageSize+" " ;
			ps = conn.prepareStatement(sql_do);
			rs = ps.executeQuery();
			
			pw.println("共有" + pageCount +"页") ;
			pw.println("<table border=1>") ;
			pw.println("<tr><th>id</th><th>品种</th></tr>") ;
			
			while(rs.next()) {
				pw.println("<tr>") ;
				pw.println("<td>"+rs.getInt(1)+"</td>") ;
				pw.println("<td>"+rs.getString(2)+"</td>") ;
				pw.println("</tr>") ;
			}
			pw.println("</table>") ;
			
			//显示上一页
			if(pageNow != 1) {
				pw.println("<a href=wel?pageNow="+(pageNow-1)+">上一页</a>") ;
			}
			for(int i = pageNow; i <= pageNow+4 ; i++) {
				pw.println("<a href=wel?pageNow="+i+">"+i+"</a>") ;
			}
			
			//显示下一页
			if(pageNow < pageCount){
				pw.println("<a href=wel?pageNow="+(pageNow+1)+">下一页</a>") ;
			}
		} catch (Exception e) {
			e.printStackTrace() ;
		} finally {
			try {
				if (rs != null) {
					rs.close() ;
					rs = null ;
				}
				if ( ps != null) {
					ps.close() ;
					ps = null ;
				}
				if (conn != null) {
					conn.close() ;
					conn = null ;
				}
			}catch(SQLException e) {
				e.printStackTrace() ;
			}
		}


 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值