在日常的开发中,做数据分页是很常见的需求了,面对各种各样的数据库或者是多数据源,有没有一种可以共用的实现方法呢,在明确数据量不大的情况下,逻辑分页不失为一种快速通用的方法,因为无须对sql语句进行修改,可以无视底层数据库的类型,不过这种方式的缺点也是显而易见的,一来就是效率低,二来会对应用端服务造成压力,所以一般情况下我们都会使用物理分页,把具体的实现和运算交给数据库服务。

物理分页的方式由数据库提供,效率高,但是不同的数据库对于分页的实现各有差异,所以首先要看一下不同数据库对于分页的sql实现:

在开始之前,我们首先定义几个常量,用以标记我们在具体实现中要替换的变量值:


  • String sqlMark = "#SQL";   本次分页的原有sql语句,例如:select * from order_info
  • String startMark = "#START_COUNT";   本次分页的开始行数
  • String endMark = "#END_COUNT";   本次分页的结束行数
  • String orderMark = "#ORDER";   本次分页的排序列(仅针对sqlserver)
  • String columnNames = "#COLUMN_NAMES";   本次分页最后要返回的列名(按需拿部分列或全部)

MySQL

select #COLUMN_NAMES from (#SQL) A limit #START_COUNT,#END_COUNT

SQL Server

select #COLUMN_NAMES from (select *,ROW_NUMBER() OVER(order by #ORDER ) AS RowId from (#SQL) AS A ) AS B where RowId between #START_COUNT and #END_COUNT

Oracle

SELECT #COLUMN_NAMES FROM (SELECT A.*,ROWNUM RN FROM (#SQL) A WHERE ROWNUM <=#END_COUNT) WHERE RN >=#START_COUNT

Hive

SELECT #COLUMN_NAMES FROM (SELECT row_number() over (ORDER BY #ORDER) AS rn,tb.* FROM (#SQL) tb) t WHERE rn > #START_COUNT AND rn < #END_COUNT

以上就是核心内容,下面来一个具体案例,一个通用的sql查询分页方法:

private Map<String,Object> startPage4Preview(String dbId, String sql, int pageIndex, int pageSize,Boolean noPagination) throws BusinessException, SQLException, RucException, IOException {Map<String, String> dbs = new HashMap<>();String sqlMark = "#SQL";String startMark = "#START_COUNT";String endMark = "#END_COUNT";String orderMark = "#ORDER";String columnNames = "#COLUMN_NAMES";dbs.put("oracle", "SELECT #COLUMN_NAMES FROM (SELECT A.*,ROWNUM RN FROM (#SQL) A WHERE ROWNUM <=#END_COUNT) WHERE RN >=#START_COUNT");dbs.put("mysql", "select #COLUMN_NAMES from (#SQL) A limit #START_COUNT,#END_COUNT");dbs.put("sqlserver", "select #COLUMN_NAMES from (select *,ROW_NUMBER() OVER(order by #ORDER ) AS RowId from (#SQL) AS A ) AS B where RowId between #START_COUNT and #END_COUNT");dbs.put("hive","SELECT #COLUMN_NAMES FROM (SELECT row_number() over (ORDER BY #ORDER) AS rn,tb.* FROM (#SQL) tb) t WHERE rn > #START_COUNT AND rn < #END_COUNT");boolean isFirstPage=false;boolean isLastPage=false;boolean haveNexPage=false;boolean havePerPage=false;Integer totalPage;//获取查询到的总行数int totalRow=getSqlCounts(dbId, sql);if (noPagination!=null&&noPagination&&totalRow>0){pageSize = totalRow;}int fromIndex=(pageIndex-1)*pageSize;int toIndex=pageIndex*pageSize;if(fromIndex==0) {isFirstPage=true;}else {havePerPage=true;}if(toIndex>=totalRow) {toIndex=totalRow;isLastPage=true;}else if (!isLastPage) {haveNexPage=true;}if(totalRow%pageSize==0) {totalPage=totalRow/pageSize;}else {totalPage=totalRow/pageSize+1;}Map<String,Object> map=new HashMap<>();map.put("pageIndex", pageIndex);map.put("totalPage", totalPage);map.put("totalCount", totalRow);map.put("pageSize", pageSize);map.put("firstPage", isFirstPage);map.put("lastPage", isLastPage);map.put("haveNexPage", haveNexPage);map.put("havePerPage", havePerPage);String dbType = getConnectionType(dbId);String newSQL = dbs.get(dbType).replace(sqlMark, sql);if("oracle".equals(dbType)) {SqlInfo sqlInfo = readSQL4SQLServer(sql);newSQL = newSQL.replace(columnNames,sqlInfo.getColumns()).replace(startMark, Integer.toString(fromIndex+1)).replace(endMark, Integer.toString(toIndex));}else if ("mysql".equals(dbType)) {SqlInfo sqlInfo = readSQL4Hive(sql);newSQL = newSQL.replace(columnNames,sqlInfo.getColumns()).replace(startMark, Integer.toString(fromIndex)).replace(endMark, Integer.toString(pageSize));}else if ("sqlserver".equals(dbType)) {SqlInfo sqlInfo = readSQL4SQLServer(sql);newSQL = newSQL.replace(columnNames,sqlInfo.getColumns()).replace(startMark, Integer.toString(fromIndex+1)).replace(endMark, Integer.toString(toIndex)).replace(orderMark, "(SELECT 1)");}else if ("hive".equalsIgnoreCase(dbType)){//hive的话 目前单表查询采用的是一种偷懒的方法,拆分sql获取字段名和表名SqlInfo sqlInfo = readSQL4Hive(sql);newSQL = newSQL.replace(columnNames,sqlInfo.getColumns()).replace(startMark, Integer.toString(fromIndex)).replace(endMark, Integer.toString(toIndex+1)).replace(orderMark, sqlInfo.getFirstColumn());}List<Map<String,Object>> select = xxxService.select(dbId, newSQL);map.put("list", select);return map;}

关于第一个参数:dbId,是存在数据库的相关数据源的主键值,可以理解为要操作的数据源的一些基本信息,后续不再说明。其他的几个参数:要分页的sql语句,当前页码数,分页大小,是否进行分页。

总的来说,此方法就是根据不同的数据源类型生成不同的分页sql,然后交给数据库去执行,然后返回统一格式的数据,供前端使用。

不再东寻西找,常见数据库分页方法都在这里了相关推荐

  1. 新版数据库分页方法(Sql server2012)

    1. ROW_NUMBER() 的分页方法 dbcc freeproccache dbcc dropcleanbuffers set statistics time on set statistics ...

  2. 数据技术初学者不用再东搜西找了,一篇文章解读20个最新数据技术概念

    老板关心技术,经常会问一些技术的问题. 有次跟老板汇报大数据,记得当时介绍到了NO SQL数据库,然后老板问起数据库的发展历史,让我说说关系型数据库以前是什么数据库,为什么会演变成这样,我一时语塞. ...

  3. mysql 分页查询web_JavaWeb分页显示内容之分页查询的三种思路(数据库分页查询)...

    JavaWeb分页显示内容之分页查询的三种思路(数据库分页查询)-1.jpg (40.23 KB, 下载次数: 0) 2018-8-18 13:34 上传 在开发过程中,经常做的一件事,也是最基本的事 ...

  4. 经典好用的list分页方法

    大多数开发人员都知道,在Web系统中,分页是一种常见的功能,我之前写的分页方法都比较麻烦,移植性也不高,这就很不乐观了. 很多时候各种条件查询完了又做一些其他的业务处理,然后就导致分页不好用了. 所以 ...

  5. java access 分页查询语句,爱不释手—几条常见的数据库分页之SQL语句代码

    我们在编写MIS系统和Web应用程序等系统时,都涉及到与数据库的交互,如果数据库中数据量很大的话,一次检索所有的记录,会占用系统很大的资源,因此我们常常采用,需要多少数据就只从数据库中取多少条记录,即 ...

  6. 东邪西毒新编 (转)

    东邪西毒新编 龙伏佑 金庸的<笑傲江湖>描写的东邪西毒南帝北丐,谁能真正说透他们?王家卫的电影<东邪西毒>尝试了一次另类解释.这里我也给他新编一次. 黄药师:心也能流出泉水 石 ...

  7. 西数DES数据库取证分析大师系统

    西数DES数据库取证分析大师系统  软件界面             功能介绍: 支持勒索病毒加密的oracle数据库 可从数据文件 DBF,dmp文件恢复表数据,存储过程,触发器等所有数据.. (1 ...

  8. [东邪西毒][程序员版][原版][剧情]

    电影名:东邪西毒 导演:王家卫 时间:1994年 地区:中国香港 主演:张国荣/梁家辉/梁朝伟/张曼玉/张学友/林青霞/ 刘嘉玲/ 杨采妮 上映日期:1994年6月18日 -------------- ...

  9. [王家卫经典武侠动作][东邪西毒:终极版][BluRay-RMVB][国粤双语]

    ◎译 名 东邪西毒:终极版 ◎片 名 Ashes of Time Redux ◎年 代 2008 ◎国 家 中国 ◎类 别 动作 ◎语 言 粤语 ◎字 幕 中文字幕 ◎IMDB评分 7.5/10 44 ...

  10. OSChina 周二乱弹 ——程序员大电影《东邪西毒》之外包风云录

    2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2017)请戳(这里) [今日歌曲] @Katy凯蒂 :嗨起来 分享Patricia Kazadi的单曲< ...

最新文章

  1. python实现反转链表讲解_基于Python实现2种反转链表方法代码实例
  2. 【重磅来袭】斯坦福开源Python版NLP库Stanza:涵盖66种语言!
  3. UITableView 重用机制
  4. ios purelayout--基础使用--进阶使用--看这就够了
  5. Linux 常用检测命令
  6. ActiveMQ添加商品发送消息
  7. c语言数组将素数放在前部,m个人的成绩存放在score数组中,请编写函数fun(),它的功能是将高于平均分的人数作为函数值返回,将_开卷宝...
  8. 安装python3.7.0的步骤_python 3.7.0 安装配置方法图文教程
  9. php软件开发--sphinx索引静态化及伪静态
  10. 华为透露中国首个开源基金会将于近期正式运营!
  11. 虚拟化解决方案 并不仅限于SDN
  12. (Foxit PDF阅读器设置)禁止改变当前缩放比例,改善书签跳转阅读体验
  13. 开放源码软件的安装(tar包安装方法)
  14. FPGA实现任意角度旋转图片
  15. win10计算机磁盘图标,win10系统本地磁盘图标显示异常如何恢复
  16. C#基于FFmpeg实现录屏功能
  17. 如何理解面向对象(POO)?
  18. NURBS Curves
  19. “动真格”的垃圾分类,需要你我容忍其中的不便
  20. Python:实现doomsday末日算法(附完整源码)

热门文章

  1. python3下载网页视频_三种下载网页视频的的方法(亲测!非常详细)
  2. Unity资源打包(AssetBundle)
  3. 【python 作日期的折线图和柱状图组合图】
  4. 作为研发面试官,亲自教你面试技巧
  5. 关于c#保存图片 图片大小改变的问题
  6. php怎么画五星红旗,php基于GD库画五星红旗的方法
  7. selenium 模拟浏览器刷新
  8. mysql索引失效口诀
  9. 2019最新计算机配置,2019年电脑配置推荐,收藏一篇文章就够了
  10. 2021年教师资格证 科目三 高中数学 课程标准 简答题