编程语言

img webeasymail

通过SELECT语句自动得到SQL SERVER分页语句和查询总条数语句!

发表于2008/9/29 20:07:00  808人阅读

分类: SQL SERVER

  1.  /*  
  2.   * @(#)SqlServer2005PageHepler.java 0.2 08/09/20  
  3.   * Copyright 2009 Zonrong, Inc. All rights reserved.  
  4.   */    
  5.      
  6.  import java.util.regex.Matcher;    
  7.  import java.util.regex.Pattern;    
  8.      
  9.  /**  
  10.   * SQL SERVER 2005 分页辅助类.  
  11.   * @author 黄明杰  
  12.   * @version 0.2  
  13.   */    
  14.  public class SqlServer2005PageHepler {    
  15.          
  16.      /**  
  17.       * 得到查询总数的SQL  
  18.       * @param querySelect 查询SQL  
  19.       * @return 得到总数的SQL  
  20.       */    
  21.      public static String getCountString(String querySelect) {    
  22.              
  23.          querySelect     = getLineText(querySelect);    
  24.          int orderIndex  = getLastOrderInsertPoint(querySelect);    
  25.              
  26.          int formIndex   = getAfterFormInsertPoint(querySelect);    
  27.          String select   = querySelect.substring(0, formIndex);    
  28.             
  29.          //如果SELECT 中包含 group by 或者 distinct 就在外层包含COUNT   
  30.          if (select.startsWith("select distinct") || isHaveGroupBy(querySelect)) {    
  31.              return new StringBuffer(querySelect.length()).append(    
  32.                      "select count(1) '_count' from (").append(    
  33.                      querySelect.substring(0, orderIndex)).append(" ) _t")    
  34.                      .toString();  
  35.            
  36.          }else {   
  37.              return new StringBuffer(querySelect.length()).append(    
  38.                      "select count (1) '_count' ").append(    
  39.                      querySelect.substring(formIndex, orderIndex)).toString();    
  40.          }    
  41.      }    
  42.          
  43.      /**  
  44.       * 得到分页的SQL  
  45.       * @param offset    偏移量  
  46.       * @param limit     限度  
  47.       * @return  分页SQL  
  48.       */    
  49.      public static String getLimitString(String querySelect,int offset, int limit) {    
  50.              
  51.          querySelect     = getLineText(querySelect);    
  52.          int orderIndex  = getLastOrderInsertPoint(querySelect);    
  53.              
  54.          StringBuilder sb = new StringBuilder(querySelect.length())    
  55.              .append("select * from (select *,ROW_NUMBER() OVER (")    
  56.              .append(querySelect.substring(orderIndex).replaceAll("[^//s,]+//."""))    
  57.              .append(") _row_num from (")    
  58.              .append(querySelect.substring(0, orderIndex)).append(") _t")    
  59.              .append(") _t where _t._row_num > ")    
  60.              .append(offset == -1 ? "?" : offset)    
  61.              .append(" and _t._row_num <=  ")    
  62.              .append(limit  == -1 ? "?" : limit);     
  63.              
  64.          return sb.toString();    
  65.      }    
  66.         
  67.      /**  
  68.       * 判断是否包含正确group by  
  69.       * @return 如果包含返回True否则返回false 
  70.       */    
  71.      private static boolean isHaveGroupBy(String querySelect){    
  72.          int groupIndex = querySelect.toLowerCase().lastIndexOf("group by");    
  73.          if (groupIndex != -1 && isBracketCanPartnership(querySelect.substring(groupIndex,querySelect.length()))) {    
  74.              return true;    
  75.          }    
  76.          return false;    
  77.      }    
  78.        
  79.      /**  
  80.       * 得到最后一个order By的插入点位置  
  81.       * @return 返回最后一个order By插入点的位置  
  82.       * @throws RuntimeException 如果不存在正确的order by  
  83.       */    
  84.      private static int getLastOrderInsertPoint(String querySelect){    
  85.          int orderIndex = querySelect.toLowerCase().lastIndexOf("order by");    
  86.          if (orderIndex == -1    
  87.                  || !isBracketCanPartnership(querySelect.substring(orderIndex,querySelect.length()))) {    
  88.              throw new RuntimeException("SQL 2005 分页必须要有Order by 语句!");    
  89.          }    
  90.          return orderIndex;    
  91.      }    
  92.      
  93.      
  94.      /**  
  95.       * 将SQL语句变成一条不换行语句,并且每个单词的间隔都是1个空格   
  96.       * @param sql 需要转化的文本  
  97.       * @return 如果sql是NULL返回空,否则返回转化后的SQL  
  98.       */    
  99.      private static String getLineText(String text) {    
  100.          return text.replaceAll("[/r/n]"" ").replaceAll("//s{2,}"" ");    
  101.      }    
  102.      
  103.      /**  
  104.       * 得到SQL第一个正确的FROM的的插入点  
  105.       * @param querySelect 完整的查询语句  
  106.       * @return  正确的FROM插入点  
  107.       */    
  108.      private static int getAfterFormInsertPoint(String querySelect) {    
  109.          String regex = "//s+FROM//s+";    
  110.          Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);    
  111.          Matcher matcher = pattern.matcher(querySelect);    
  112.          while (matcher.find()) {    
  113.              int fromStartIndex = matcher.start(0);    
  114.              String text = querySelect.substring(0, fromStartIndex);    
  115.              if (isBracketCanPartnership(text)) {    
  116.                  return fromStartIndex;    
  117.              }    
  118.          }    
  119.          return 0;    
  120.      }    
  121.      
  122.      /**  
  123.       * 判断括号'()'是否匹配  
  124.       * @param text  要判断的文本  
  125.       * @return 如果匹配返回TRUE,否则返回FALSE  
  126.       */    
  127.      private static boolean isBracketCanPartnership(String text) {    
  128.          if (text == null    
  129.                  || (getIndexOfCount(text, '(') != getIndexOfCount(text, ')'))) {    
  130.              return false;    
  131.          }    
  132.          return true;    
  133.      }    
  134.      
  135.      /**  
  136.       * 得到一个字符在另一个字符串中出现的次数  
  137.       * @param text  文本  
  138.       * @param ch    字符  
  139.       * @return 字符出现在文本的次数.  
  140.       */    
  141.      private static int getIndexOfCount(String text, char ch) {    
  142.          int count = 0;    
  143.          for (int i = 0; i < text.length(); i++) {    
  144.              count = (text.charAt(i) == ch) ? count + 1 : count;    
  145.          }    
  146.          return count;    
  147.      }    
  148.  } 
因为公司用SQL SERVER 2005 , SQL SERVER 2000 就不想扩展了,里面已经提供了方法,可以比较方便的转换成SQL SERVER 2000的分页语句即可!

 

 

注意:

 不支持"UNION" 和“UNION ALL” 这样的结果合并语句,例如:

   1.  select * from dbo.[user] 
   2.  union 
   3.  select top 1 * from dbo.[user] order by age

 主要原因是 UNION  这样的语句没有共同的order by 条件,所以不想支持,如果你需要得到正确的结果你需要这样写,如下:

   1.  select * from ( 
   2.      select * from dbo.[user] 
   3.      union  
   4.      select top 1 * from dbo.[user] order by age 
   5.  ) Q order by id 
阅读全文
0 0

相关文章推荐

img
取 消
img