자바 Sql 구문 분석 실현

최근 에 간단 하고 간단 한 데이터 베이스 시스템 을 실현 하려 면 데 이 터 를 어떻게 효율적으로 저장 하고 방문 하 는 지 를 고려 하고 표 관 계 를 구축 하 는 것 을 제외 하고 기본 적 인 sql 조회 문 구 를 분석 해 야 사용자 의 조회 요 구 를 알 수 있다.시간 관계 상 기 존의 글 을 참고 하고 그 실현 과정 에서 발생 한 작은 문 제 를 수정 하여 여러분 과 공유 하 겠 습 니 다.원문 을 찾 아 보십시오http://www.cnblogs.com/pelephone/articles/sql-parse-single-word.html
첫 번 째 단계: sql 문 구 를 미리 처리 합 니 다.
사용자 에 대해 우 리 는 각종 형식의 조회 문 구 를 작성 하고 한 줄 또는 여러 줄, 문장의 한 칸 또는 여러 칸 의 간격 등 을 받 아들 여야 한다.그러나 우 리 는 sql 문 구 를 해석 하려 면 먼저 그것들 을 표준화 시 켜 야 다음 단계 에 처리 할 수 있다.시스템 의 처리 요구 사항:
1) SQL 문장의 앞 뒤 공백 을 없 애고 연속 공백 문자 (빈 칸, TAB, 리 턴 줄 포함) 를 하나의 빈 칸 으로 교체 합 니 다.
2) sql 문 구 를 모두 소문 자 형식 (또는 대문자 형식) 으로 바 꿉 니 다.
3) SQL 문장의 끝 에 끝 기호 인 'ENDOFSQL' (원인 뒤에 설명) 을 붙인다.
예 를 들 어 사용자 입력: "select c1, c2, c3 from t1, t2, t3 where condi 1 = 5 and condi 6 = 6 or condi 7 = 7 order
by g1,g2”
사전 처 리 를 통 해 "select c1, c2, c3 from t1, t2, t3 where condi 1 = 5 and condi 6 = 6 or condi 7 = 7 order"로 해 야 합 니 다. by g1,g2”
두 번 째 단계: 검색 어 를 구문 블록 으로 나 눕 니 다.
검색 어 를 예 로 들 면 (본 고 는 검색 어 를 예 로 들 어 설명 하고 다른 삭제, 삽입 등 문장의 원 리 는 이와 유사 하 다. 검색 어가 상대 적 으로 복잡 하기 때문에 i 로 설명 한다). 위 에서 우리 가 표준화 한 문구 처럼 우 리 는 다음 단계 의 표 에서 데 이 터 를 처리 해 야 한다. 먼저 그 표 에 대한 처리 임 을 알 아야 한다.그 조건 을 만족 시 키 려 면 그 속성 을 출력 하고 어떤 순서 로 출력 해 야 합 니까?그래서 검색 어 는 다음 과 같은 몇 개의 블록 으로 나 눌 수 있다.
1) select c1, c2, c3 from: 속성 출력 블록;블록 (start) select, 블록 끝 (end) from, 우리 가 관심 을 가 지 는 정보 (body): c1, c2, c3;다음 블록 유사 분석
2)from....where; 데이터 시트 블록 관련.
3)where.....order by; 검색 조건 블록.
4)order by.....ENDOFSQL; 속성 출력 순서.여기 서도 우리 가 왜 검색 어 끝 에 끝 자 를 붙 여야 하 는 지 알 수 있다. 이것 은 마지막 블록의 한정 수 요 를 위 한 것 이다.
블록 을 어떻게 나 누 는 지 알 게 되 었 습 니 다. 그 다음 에 해 야 할 일 은 바로 우리 가 표준 화 된 sql 구문 에서 줄 블록 을 자 르 는 것 입 니 다. 여기 서 우 리 는 정규 표현 식 을 사 용 했 습 니 다. 두 번 째 블록 from... where 의 조 회 를 예 로 들 어 분석 을 하 겠 습 니 다.
"(from)(.+)( where | on | having | group by | order by | ENDOFSQL)“
이상 은 두 번 째 블록의 정규 일치 식 (다른 블록의 일치 식 아래 에서 도 제 시 됩 니 다) 입 니 다. 이 를 통 해 알 수 있 듯 이 sql 검색 어 에서 from 블록 에서 from 와 조합 하 는 것 은 where 뿐만 아니 라 on, having, group by 등 도 나타 날 수 있 습 니 다. 그러면 이 정규 식 을 통 해 저 희 는 다음 과 같은 블록 을 얻 을 수 있 습 니 다.
      from .... where
  from .... on
  from .... having
  from .... group by
  from .... order by
  from .... ENDOFSQL
여기 서 주의해 야 할 것 은 정규 식 으로 sql 문 구 를 일치 시 킬 때 전체 sql 문 구 를 일치 시 킬 수 없다 는 것 입 니 다. 정규 매 칭 은 욕심 매 칭 이기 때문에 가능 한 한 뒤로 찾 아 최대 구문 에 일치 합 니 다. 상기 문 구 를 예 로 들 어 전체 sql 문 구 를 일치 시 키 면 from... wh 가 아 닙 니 다.ere 이 문 구 는 from... where... orderby 입 니 다. 이것 은 우리 가 원 하 는 것 이 아 닙 니 다. 따라서 우 리 는 효율 을 희생 할 수 밖 에 없습니다. 전체 sql 문 구 를 점차적으로 조회 하 는 방식 으로 해당 하 는 문 구 를 찾 을 수 있 습 니 다. 검색 과정 을 제시 하고 이 해 를 강화 할 수 있 습 니 다. 상기 sql 문 구 를 예 로 들 어 첫 번 째 문 구 를 찾 는 과정 은?
s se sel sele selec select select select c select c1 select c1, select c1,c select c1,c2 select c1,c2, select c1,c2,c select c1,c2,c3 select c1,c2,c3 select c1,c2,c3 f select c1,c2,c3 fr select c1,c2,c3 fro select c1,c2,c3 from
이렇게 하면 첫 번 째 블록 을 찾 을 수 있 습 니 다. 이런 식 으로 유추 하여 두 번 째 블록 을 찾 을 때 다시 처음부터 하나씩 찾 습 니 다.
세 번 째 단계: 각 블록 을 찾 았 습 니 다. 우 리 는 우리 가 가장 관심 을 가 지 는 정 보 를 추출 해 야 합 니 다. 바로 문장의 덩치 와 꼬리 사이 에 끼어 있 는 body 부분 입 니 다. 이것 이 바로 실현 되 었 습 니 다. 일반적인 sql 문 구 는 쉼표 로 분할 되 고 우 리 는 각 조각의 body 정 보 를 추출 합 니 다.
절차 소개 끝 났 습 니 다. 다음은 코드 를 올 리 고 즐 기세 요. 소년!
package com.sitinspring.common.sqlparser.single;

import java.util.List;

/** *//**
*   Sql       
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class SqlParserUtil{
    /** *//**
     *        
     * @param sql:    sql  
     * @return       
     */
    public String getParsedSql(String sql){
        sql=sql.trim();
        sql=sql.toLowerCase();
        sql=sql.replaceAll("\\s{1,}", " ");
        sql=""+sql+" ENDOFSQL";
        //System.out.println(sql);
        return SingleSqlParserFactory.generateParser(sql).getParsedSql();
    }
    
    /** *//**
     * SQL       
     * @param sql:    sql  
     * @return       
     */
    public List getParsedSqlList(String sql)
    {
        sql=sql.trim();
        sql=sql.toLowerCase();
        sql=sql.replaceAll("\\s{1,}", " ");
        sql=""+sql+" ENDOFSQL";
        //System.out.println(sql);
        return SingleSqlParserFactory.generateParser(sql).RetrunSqlSegments();
    }
    }
package com.sitinspring.common.sqlparser.single;

//import com.sitinspring.common.sqlparser.single.NoSqlParserException;
import java.util.ArrayList;
import java.util.List;
import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*   Sql   ,         
* @author    ()
*
* @since 2013-6-10
* @version 1.00
*/
public abstract class BaseSingleSqlParser{
/** *//**
 *   Sql  
 */
protected String originalSql;
/** *//**
 * Sql    
 */
protected List segments;
/** *//**
 *     ,    Sql  ,    。
 * @param originalSql
 */
public BaseSingleSqlParser(String originalSql){
    this.originalSql=originalSql;
    segments=new ArrayList();
    initializeSegments();
    splitSql2Segment();
}
/** *//**
 *    segments,      
 *
 */
protected abstract void initializeSegments();
/** *//**
 *  originalSql        
 *
 */
protected void splitSql2Segment() {
    for(SqlSegment sqlSegment:segments)
    {
        sqlSegment.parse(originalSql);
    }
}
/** *//**
 *        Sql  
 * @return
 */
public String getParsedSql() {
    
    //           
    /*
    for(SqlSegment sqlSegment:segments)
    {
        String start=sqlSegment.getStart();
        String end=sqlSegment.getEnd();
        System.out.println(start);
        System.out.println(end);
    }
    */
    
    StringBuffer sb=new StringBuffer();
    for(SqlSegment sqlSegment:segments)
    {
        sb.append(sqlSegment.getParsedSqlSegment());
    }
    String retval=sb.toString().replaceAll("@+", "
"); return retval; } /** *//** * Sql * @return */ public List RetrunSqlSegments() { int SegmentLength=this.segments.size(); if(SegmentLength!=0) { List result=this.segments; return result; } else { //throw new Exception(); return null; } } }
package com.sitinspring.common.sqlparser.single;

import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*
*          
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class DeleteSqlParser extends BaseSingleSqlParser{
public DeleteSqlParser(String originalSql) {
    super(originalSql);
}
@Override
protected void initializeSegments() {
    segments.add(new SqlSegment("(delete from)(.+)( where | ENDOFSQL)","[,]"));
    segments.add(new SqlSegment("(where)(.+)( ENDOFSQL)","(and|or)"));
}
}
package com.sitinspring.common.sqlparser.single;

import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*
*            
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class InsertSelectSqlParser extends BaseSingleSqlParser{
public InsertSelectSqlParser(String originalSql) {
    super(originalSql);
}
@Override
protected void initializeSegments() {
    segments.add(new SqlSegment("(insert into)(.+)( select )","[,]"));
    segments.add(new SqlSegment("(select)(.+)(from)","[,]"));
    segments.add(new SqlSegment("(from)(.+)( where | on | having | groups+by | orders+by | ENDOFSQL)","(,|s+lefts+joins+|s+rights+joins+|s+inners+joins+)"));
    segments.add(new SqlSegment("(where|on|having)(.+)( groups+by | orders+by | ENDOFSQL)","(and|or)"));
    segments.add(new SqlSegment("(groups+by)(.+)( orders+by| ENDOFSQL)","[,]"));
    segments.add(new SqlSegment("(orders+by)(.+)( ENDOFSQL)","[,]"));
}
}
package com.sitinspring.common.sqlparser.single;

import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*
*          
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class InsertSqlParser extends BaseSingleSqlParser{
public InsertSqlParser(String originalSql) {
    super(originalSql);
}
@Override
protected void initializeSegments() {
    segments.add(new SqlSegment("(insert into)(.+)([(])","[,]"));
    segments.add(new SqlSegment("([(])(.+)( [)] values )","[,]"));
    segments.add(new SqlSegment("([)] values [(])(.+)( [)])","[,]"));
}
@Override
public String getParsedSql() {
    String retval=super.getParsedSql();
    retval=retval+")";
    return retval;
}
}




package com.sitinspring.common.sqlparser.single;

public class NoSqlParserException extends Exception{
    private static final long serialVersionUID = 1L;
    NoSqlParserException()
    {
        
    }
    NoSqlParserException(String sql)
    {
        //      
        super(sql);
    }
}
package com.sitinspring.common.sqlparser.single;

import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*
*          
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class SelectSqlParser extends BaseSingleSqlParser{
public SelectSqlParser(String originalSql) {
    super(originalSql);
}
@Override
protected void initializeSegments() {
    segments.add(new SqlSegment("(select)(.+)(from)","[,]"));
    segments.add(new SqlSegment("(from)(.+)( where | on | having | group by | order by | ENDOFSQL)","(,| left join | right join | inner join )"));
    segments.add(new SqlSegment("(where|on|having)(.+)( group by | order by | ENDOFSQL)","(and|or)"));
    segments.add(new SqlSegment("(group by)(.+)( order by| ENDOFSQL)","[,]"));
    segments.add(new SqlSegment("(order by)(.+)( ENDOFSQL)","[,]"));
}
}
package com.sitinspring.common.sqlparser.single;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
//import com.sitinspring.common.sqlparser.single.NoSqlParserException;
/** *//**
*   Sql       
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class SingleSqlParserFactory{
public static BaseSingleSqlParser generateParser(String sql)
{
    if(contains(sql,"(insert into)(.+)(select)(.+)(from)(.+)"))
    {
        return new InsertSelectSqlParser(sql);
    }
    else if(contains(sql,"(select)(.+)(from)(.+)"))
    {
        return new SelectSqlParser(sql);
    }
    else if(contains(sql,"(delete from)(.+)"))
    {
        return new DeleteSqlParser(sql);
    }
    else if(contains(sql,"(update)(.+)(set)(.+)"))
    {
        return new UpdateSqlParser(sql);
    }
    else if(contains(sql,"(insert into)(.+)(values)(.+)"))
    {
        return new InsertSqlParser(sql);
    }
    //sql=sql.replaceAll("ENDSQL", "");
    else
        return new InsertSqlParser(sql);
       //throw new NoSqlParserException(sql.replaceAll("ENDOFSQL", ""));//      
}
/** *//**
 *  word   lineText   ,       
 * @param sql:    sql  
 * @param regExp:     
 * @return
 */
private static boolean contains(String sql,String regExp){
    Pattern pattern=Pattern.compile(regExp,Pattern.CASE_INSENSITIVE);
    Matcher matcher=pattern.matcher(sql);
    return matcher.find();
}
}
package com.sitinspring.common.sqlparser.single;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** *//**
* Sql    
*
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class SqlSegment{
private static final String Crlf = "@";
private static final String FourSpace = "  ";
/** *//**
 * Sql        
 */
private String start;
/** *//**
 * Sql        
 */
private String body;
/** *//**
 * Sql        
 */
private String end;
/** *//**
 *               
 */
private String bodySplitPattern;
/** *//**
 *           
 */
private String segmentRegExp;
/** *//**
 *     Body   
 */
private List bodyPieces;
/** *//**
 *     
 * @param segmentRegExp     Sql        
 * @param bodySplitPattern     body      
 */
public SqlSegment(String segmentRegExp,String bodySplitPattern){
    start="";
    body="";
    end="";
    this.segmentRegExp=segmentRegExp;
    this.bodySplitPattern=bodySplitPattern;
    this.bodyPieces=new ArrayList();
    
}
/** *//**
 *  sql     segmentRegExp   ,    start,body,end      
 * @param sql
 */
public void parse(String sql){
    Pattern pattern=Pattern.compile(segmentRegExp,Pattern.CASE_INSENSITIVE);
    for(int i=0;i<=sql.length();i++)
    {
     String shortSql=sql.substring(0, i);
     //           
     System.out.println(shortSql);
     Matcher matcher=pattern.matcher(shortSql);
     while(matcher.find())
     {
         start=matcher.group(1);
         body=matcher.group(2);
         //  body  
         //System.out.println(body);
         end=matcher.group(3);
         //     end  
         //System.out.println(end);
         parseBody();
         return;
     }
    }
}
/** *//**
 *   body  
 *
 */
private void parseBody(){
    
    List ls=new ArrayList();
    Pattern p = Pattern.compile(bodySplitPattern,Pattern.CASE_INSENSITIVE);
    //         
    body=body.trim();
    Matcher m = p.matcher(body);
    StringBuffer sb = new StringBuffer();
    boolean result = m.find();
    while(result)
    {
        m.appendReplacement(sb, m.group(0) + Crlf);
        result = m.find();
    }
    m.appendTail(sb);
    //       
    String[] arr=sb.toString().split(" ");
    int arrLength=arr.length;
    for(int i=0;i

수행 결과: 자신 이 테스트 클래스 를 썼 다.
package com.sitinspring.common.sqlparser.single;

import com.sitinspring.common.sqlparser.single.SqlSegment;
/** *//**
*
*          
* @author    
*
* @since 2013-6-10
* @version 1.00
*/
public class UpdateSqlParser extends BaseSingleSqlParser{
public UpdateSqlParser(String originalSql) {
    super(originalSql);
}
@Override
protected void initializeSegments() {
    segments.add(new SqlSegment("(update)(.+)(set)","[,]"));
    segments.add(new SqlSegment("(set)(.+)( where | ENDOFSQL)","[,]"));
    segments.add(new SqlSegment("(where)(.+)( ENDOFSQL)","(and|or)"));
}
}
import java.util.List;

import com.sitinspring.common.sqlparser.single.*;
public class Test {
    /** *//**
    *   Sql       
    * @author    
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
       //String test="select  a from  b " +
           //    "
"+"where a=b"; //test=test.replaceAll("\\s{1,}", " "); //System.out.println(test); // String testSql="select c1,c2,c3 from t1,t2 where condi3=3 "+"
"+" or condi4=5 order by o1,o2"; SqlParserUtil test=new SqlParserUtil(); String result=test.getParsedSql(testSql); System.out.println(result); //List result=test.getParsedSqlList(testSql);// } }

좋은 웹페이지 즐겨찾기