视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
智能将SqlServer的查询语句转换为分页语句
2020-11-09 08:03:41 责编:小采
文档


主要用到了jsqlparser,前面有篇博客介绍过: JAVA - Sql解析工具jsqlparser简单使用 为了给Mybatis分页插件增加对sqlserver的支持,专门写了这样一个的工具,只依赖jsqlparser。 这个类不仅是为了给分页插件使用的,他还能使用,使用它你可以方便的

主要用到了jsqlparser,前面有篇博客介绍过:

JAVA - Sql解析工具jsqlparser简单使用


为了给Mybatis分页插件增加对sqlserver的支持,专门写了这样一个的工具,只依赖jsqlparser。

这个类不仅是为了给分页插件使用的,他还能使用,使用它你可以方便的生成一个分页查询。


分页插件地址:Mybatis_PageHelper

SqlServer分页转换完整代码:com/github/pagehelper/SqlServer.java


简单讲一下处理的逻辑:


通过对SqlServer进行分析,利用jsqlparser方便的解析,然后对sql结构进行修改,生成最后的分页语句。


首先一个sql通常有两种情况,一种是普通的一个select查询,一种是通过union,minus等连接的多个查询。


当发现是多个查询的时候,会在原来的SQL基础上在外面包含一层查询,让原来的查询变成子查询。

外层的查询会从多个查询中的第一个查询中提取查询列(有别名的使用别名),因为每个查询的列都是一样的,所以找一个提取就行。

另外在多个SQL中的最后一个相比其他来说可能会多一些条件,这里主要考虑的是order by,如果有order by语句,会把order by移到外层SQL上。


做完上面的处理后,就和第一种普通的一个select查询一样了。


接下来处理这一个select查询。

第一步先获取查询列,并且会对别名和表名进行一些特殊处理。

第二步给SQL增加ROW_NUMBER(),将order by提取到OVER中

第三步处理全部子查询,如果子查询包含order by,会增加top 100 percent

第四步在select查询外包一层TOP查询。


经过上面的步骤就能得到一个合理结构的分页查询了。


其中有一些细节性的东西jsqlparser都考虑到了,不需要自己去特殊处理,例如distinct。


下面是两个例子。


这个类是的,使用的时候可以初始化一个,然后直接调用方法即可。

初始化:

public static final SqlServer sqlServer = new SqlServer();


第一个,多个查询UNION ALL

@Test
public void testSqlUnion() throws JSQLParserException {
 String originalSql = "select countryname,countrycode code from country where id >170 " +
 "union all " +
 "select countryname,countrycode code from country where id < 10 order by code";
 System.out.println(sqlServer.convertToPageSql(originalSql, 1, 10));
}

生成的SQL如下(经过人工格式化):
SELECT TOP 10 PAGE_TABLE_ALIAS.countryname, PAGE_TABLE_ALIAS.code
 FROM (SELECT ROW_NUMBER() OVER(ORDER BY code) PAGE_ROW_NUMBER,
 WRAP_OUTER_TABLE.countryname,
 WRAP_OUTER_TABLE.code
 FROM ((SELECT countryname, countrycode code
 FROM country
 WHERE id > 170) UNION ALL
 (SELECT countryname, countrycode code
 FROM country
 WHERE id < 10)) AS WRAP_OUTER_TABLE) AS PAGE_TABLE_ALIAS
 WHERE PAGE_ROW_NUMBER > 1
 ORDER BY PAGE_ROW_NUMBER


第二个,简单查询

@Test
public void testSqlDistinct() throws JSQLParserException {
 String originalSql = "select distinct countrycode,countryname from country order by countrycode";
 System.out.println(sqlServer.convertToPageSql(originalSql, 1, 10));
}

生成的SQL如下(经过人工格式化):
SELECT TOP 10 PAGE_TABLE_ALIAS.countrycode, PAGE_TABLE_ALIAS.countryname
 FROM (SELECT DISTINCT ROW_NUMBER() OVER(ORDER BY countrycode) PAGE_ROW_NUMBER,
 countrycode,
 countryname
 FROM country) AS PAGE_TABLE_ALIAS
 WHERE PAGE_ROW_NUMBER > 1
 ORDER BY PAGE_ROW_NUMBER


注意:

1.由于需要提取order by,所以尽可能保证最外层的SQL包含order by

2.如果没有order by,那么上面调用的convertToPageSql还有第四个参数orderBy

public String convertToPageSql(String sql, int offset, int limit, String orderBy) 

如果原来的sql有order by,那么通过该方法指定orderBy之后会覆盖原sql中的order by

人为指定的时候很难把握字段名字的写法,所以建议在sql中带上order by

下载本文
显示全文
专题