oracle 、MySql分页 举例

本文介绍了一种使用Hibernate结合MySQL和Oracle进行高效分页查询的方法,包括SQL查询语句的构造和执行过程,以及如何通过调整参数提高查询效率。

三重循环

select mbid00,mbmc00, llurl0,cfwz00,mbsltp,sycs00,lrsj00 from (
select mbid00,mbmc00, llurl0,cfwz00,mbsltp,sycs00,lrsj00,rownum as con from (
select * from JZ_MBXXB0 where 1=1 and lbid00=
'201'
order by lrsj00)
where rownum<=
10
) where con>=
1

在hibernate + Mysql 方式

/** * 分页查询 */ @SuppressWarnings("unchecked") public List doSearch(PageDao pageDAO, final int pageSize, final String name00) throws Exception { List list = new ArrayList(); StringBuffer sql = new StringBuffer( "from Book b where b.name00 LIKE '%"); sql.append(name00); sql.append("%'"); final String typeSql = new String(sql); // 设置每页显示条数 pageDAO.setPagesize(pageSize); int pagesize = pageDAO.getPagesize(); // 获取总记录数 List count = (List)hibernateTemplate.execute( new HibernateCallback(){ public Object doInHibernate(Session session) throws HibernateException, SQLException{ Query q = session.createQuery(typeSql); //q.setFirstResult(0); //q.setMaxResults(2); List ss =q.list(); return q.list(); //没查到数据也不会返回null, 只能用isEmpty } } ); pageDAO.getRsCountForSQL(count.size()); // 获取总页数 pageDAO.GetPageCount(); // 获取当前页 final int currpage = pageDAO.GetCurrentPageForRequest(); // 设置工具条类型 String pool = pageDAO.pagetool(PageDao.Text); //System.out.println(pageDAO.getParamUrl()); List<BookDTO> dt = new ArrayList<BookDTO>(); List rs = (List)hibernateTemplate.execute( new HibernateCallback(){ public Object doInHibernate(Session session) throws HibernateException, SQLException{ Query q = session.createQuery(typeSql); q.setFirstResult((currpage - 1) * pageSize); q.setMaxResults(pageSize);//currpage * List ss =q.list(); return q.list(); //没查到数据也不会返回null, 只能用isEmpty } } ); for (Iterator it = rs.iterator(); it.hasNext();) { Object obj = it.next(); BookDTO dto = new BookDTO(); BeanUtils.copyProperties(obj,dto); dt.add(dto); } //session.setAttribute("pagedto", pageDAO); list.add(0,dt); list.add(1,pool); return list; }


hibernate + Oracle 方式 效率较差

public List queryMbList(final PageDao pageDAO, final int pageSize, String lbid) { List list = new ArrayList(); StringBuffer sql = new StringBuffer(); StringBuffer hql = new StringBuffer(); sql = new StringBuffer( "select * from JZ_MBXXB0 where 1=1 and lbid00='"); sql.append(lbid); sql.append("'"); } // 设置每页显示条数 pageDAO.setPagesize(pageSize); @SuppressWarnings("unused") int pagesize = pageDAO.getPagesize(); // 获取总记录数 List count = persistence.executeSQLQuery(sql.toString()); pageDAO.getRsCountForSQL(count.size()); // 获取总页数 pageDAO.GetPageCount(); // 获取当前页 int currpage = pageDAO.GetCurrentPageForRequest(); // 设置工具条类型 String pool = pageDAO.pagetool(PageDao.Text); hql = new StringBuffer( "select mbid00,mbmc00, llurl0,cfwz00,mbsltp,sycs00,lrsj00 from ( "); hql.append("select mbid00,mbmc00, llurl0,cfwz00,mbsltp,sycs00,lrsj00,rownum as con from ("); if(lbid.equals("200")){ hql.append("select * from JZ_MBXXB0 where 1=1"); }else{ hql.append("select * from JZ_MBXXB0 where 1=1 and lbid00='"); hql.append(lbid); hql.append("'"); } hql.append("order by sycs00 desc,lrsj00 desc)"); //按条件排序 hql.append(" where rownum<="); hql.append(currpage * pageSize); //显示到第几条 hql.append(") where con>="); //从第几行开始显示 hql.append((currpage - 1) * pageSize + 1); List<Mbxxb0DTO> dt = new ArrayList<Mbxxb0DTO>(); List rs = persistence.executeSQLQuery(hql.toString()); for (Iterator it = rs.iterator(); it.hasNext();) { Object obj = it.next(); Mbxxb0DTO dto = new Mbxxb0DTO(); BeanHelper.copyProperties(obj,dto); dt.add(dto); } list.add(0,dt); list.add(1,pool); return list; }


<think>好的,用户问的是Oracle分页查询,特别是0-5和5-10这样的范围。首先,我需要确认用户是想了解如何实现分页查询,比如从第0行到第5行,然后是第5行到第10行这样的分页方式。Oracle分页通常使用ROWNUM或者ROW_NUMBER()函数,可能还会涉及到子查询。 用户可能对分页查询的基本原理不太清楚,特别是Oracle和其他数据库(比如MySQL)的区别。需要解释清楚ROWNUM的工作机制,因为它在排序前后会有不同的表现,容易让新手困惑。比如,直接对ROWNUM过滤可能会得到不正确的结果,需要先排序再使用子查询生成正确的行号。 另外,用户提到的0-5和5-10,可能是指页码或者行号,但Oracle的行号是从1开始的,所以可能需要调整。比如,第一页是1-5,第二页是6-10,但用户可能习惯从0开始计数,所以需要确认是否需要处理这种情况。 接下来要考虑不同的Oracle版本是否有不同的方法,比如12c之后有OFFSET-FETCH子句,但用户可能使用的是旧版本,所以需要同时介绍传统的方法和新的方法。 然后,我需要组织回答的结构,先介绍基本概念,再分步骤说明两种方法:传统ROWNUM方式和ROW_NUMBER()窗口函数,以及12c后的方法。每个步骤给出示例SQL,并解释关键点,比如为什么要使用嵌套子查询,为什么要给ROWNUM起别名等。 还需要注意用户可能遇到的问题,比如排序对分页的影响,必须确保每次分页查询的排序是一致的,否则数据可能会错乱。此外,性能方面,当数据量大的时候,分页查询的效率如何优化,可能需要索引的支持。 最后,检查是否有遗漏的情况,比如用户可能实际需求是从0开始的行号,比如0-5行对应第1到5条数据,这时候需要调整查询条件中的数字,可能需要解释清楚ROWNUM是从1开始的,避免混淆。 总结下来,回答应该分步骤,先讲原理,再讲方法,每种方法举例说明,并指出注意事项,确保用户能逐步理解和应用。</think>Oracle 数据库实现分页查询的核心是通过 `ROWNUM` 伪列或 `ROW_NUMBER()` 窗口函数控制返回的数据范围。以下是分步说明: --- ### **一、分页原理** 1. **`ROWNUM` 特性** - Oracle 为查询结果自动生成的行号(从 1 开始递增) - **必须嵌套子查询**:直接对 `ROWNUM` 过滤会因执行顺序导致错误,需先排序再分页 2. **分页公式** - 假设每页显示 *N* 条,查询第 *K* 页数据: $$ \text{起始行} = (K-1) \times N + 1 $$ $$ \text{结束行} = K \times N $$ --- ### **二、实现 0-5 和 5-10 分页** #### **方法 1:使用 `ROWNUM`(传统方式)** ```sql -- 查询第 1 页(0-5 行,实际对应 ROWNUM 1-5) SELECT * FROM ( SELECT t.*, ROWNUM rn FROM ( SELECT * FROM 表名 ORDER BY 排序字段 -- 先排序 ) t WHERE ROWNUM <= 5 -- 结束行 ) WHERE rn >= 1; -- 起始行 -- 查询第 2 页(5-10 行,实际对应 ROWNUM 6-10) SELECT * FROM ( SELECT t.*, ROWNUM rn FROM ( SELECT * FROM 表名 ORDER BY 排序字段 ) t WHERE ROWNUM <= 10 ) WHERE rn >= 6; ``` #### **方法 2:使用 `ROW_NUMBER()`(推荐)** ```sql -- 查询第 1 页(0-5 行) SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY 排序字段) rn FROM 表名 t ) WHERE rn BETWEEN 1 AND 5; -- 查询第 2 页(5-10 行) SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY 排序字段) rn FROM 表名 t ) WHERE rn BETWEEN 6 AND 10; ``` #### **方法 3:Oracle 12c+ 的 `OFFSET-FETCH` 语法** ```sql -- 查询第 1 页(0-5 行) SELECT * FROM 表名 ORDER BY 排序字段 OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY; -- 查询第 2 页(5-10 行) SELECT * FROM 表名 ORDER BY 排序字段 OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY; ``` --- ### **三、关键注意事项** 1. **排序一致性** 分页时必须确保 `ORDER BY` 相同,否则数据顺序混乱 2. **性能优化** - 对排序字段建立索引 - 避免深层分页(如查询第 1000 页),可结合条件过滤 3. **起始行计算** Oracle 行号从 1 开始,"0-5" 实际对应 `rn BETWEEN 1 AND 5` --- ### **四、示例说明** 假设表 `employees` 按 `salary` 降序分页: ```sql -- 查询第 1 页(最高薪的 5 人) SELECT * FROM ( SELECT e.*, ROW_NUMBER() OVER (ORDER BY salary DESC) rn FROM employees e ) WHERE rn <= 5; ``` 通过上述方法,可灵活控制分页范围和排序逻辑。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值