자바 Sql 구문 분석 실현
첫 번 째 단계: 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);//
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 의 부동 소수점 표시 방법먼저 십 진법 의 부동 소수점 을 이 진 으로 바 꾸 는 부동 소수점 을 두 부분 으로 나 눕 니 다. 한 숫자 에 대해 플 로 트 와 의 범 위 를 초과 하지 않 고 소수 부분 이 무한 소수 가 아니라면 대응 하 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.