`
yuexiaodong
  • 浏览: 70363 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JavaCC初探-T-SQL转换为P-SQL

阅读更多

         前段时间,研究数据库迁移工作,使用Powerdesigner实现了数据库对象之间的转换,但是由于项目中使用了大量的存储过程、函数和触发器等,想着怎么实现这些代码的迁移,网上搜了一通,大概有两个工具(SQLWays和SwisSQL,具体可以百度),后来也使用了一种工具,但是转换效果不是特别好,需要手工重新修改。这些都是后话;还有一个思路,就是使用javaCC进行在词法语法级别进行转换。首先将T-SQL进行词法分析,语法分析,最后按照P-SQL语法规则进行重新生成。由于时间进度和难度,我也只是简单识别了一些语句,下面写个简单例子,以后有时间继续研究。javaCC的安装不再叙述,附件中是安装文件和示例;

需要转换的语句:

CREATE   FUNC  test(@pdata varchar(20), @pint int(10))   RETURN  varchar(30)

 在Eclipse建立一个文件sql.jj,注意规则里面的符号都是全英文状态下的

/**
 * JavaCC file
 */
 
options {
  JDK_VERSION = "1.5";
  STATIC = true ; //生成非静态类
  LOOKAHEAD=1;//向前看2个字母,消除歧义用的
  DEBUG_PARSER = true;//以debug形式生成,便于调试 
}
PARSER_BEGIN(eg1)
package cn.heu.javacct.sql;
import java.lang.StringBuffer; 
import java.io.StringReader; 
import java.io.Reader;
public class eg1 {
	private static StringBuffer sqlSB; 
	
	
	public eg1(String s){
	this((Reader)(new StringReader(s))); 
	sqlSB = new StringBuffer();
	}

	 public String getSQL() 
    { 
        return sqlSB.toString(); 
    } 
     
    public String convert(){
    	String temp="";
    	try 
		{ 
          temp= convertSQL();
		}
       catch(Exception e) 
        { 
            e.printStackTrace(); 
        }
        return temp; 
    }
    
    
    public static void main(String args[]) throws ParseException {
  	
  	eg1 parser =null;
    try 
        { 
                String query = "  -- "+
               " CREATE   FUNC  test(@pdata varchar(20),@pint int(10))   RETURN  varchar(30) ";
                parser = new eg1(query);
      		  //  parser.convert(); 
      		    System.out.println("OLDSQL:"+query);
                System.out.println("SQL:"+ parser.convert());           
             
        } 
        catch(Exception e) 
        { 
              e.printStackTrace(); 
        } 
}

}
PARSER_END(eg1)

SKIP :
{
 	" "
|	"\r"
|	"\t"
|	"\n"
|   "--"
}
 
TOKEN:/* ms SQL keywords*/
{
   < CREATE:" CREATE "|" create " >
  |< ALTER:" ALTER "|" alter " >
  |< FROM : " from " > 
  |< FUNCNAME:<FUNCNAME> >
  |< FUNCTION :" FUNC "|" FUNCTION "|" func "|" function " >  
  |< PROCEDURE:" PROCEDURE "|" PROC "|" procedure "|" proc " >
  |< RETURN:" RETURN "|" return " >
  |< _begin:" begin "|" BEGIN " >
  |< _end:" end "|" END " >
  |< #FUNCNAME :(["0" - "9","A" - "Z","a" - "z"])+ >
}

TOKEN:/* ms SQL datatype */
{
	
    < VARCHAR:"varchar("<NUM>")" >
   |< INT:"int"<NUM> >
   |< #NUM:(["0" - "9"])+>
}

TOKEN:
{
   <papams:"("(<PARAM>|<PARAM>","<PARAM>|<PARAM>(","<PARAM>",")+<PARAM>)")"  >
  |<#PARAM:<p_data>" "<p_type>>
  |<#p_data:(["0" - "9","A" - "Z","a" - "z","@"])+>
  |<#p_type:<p_varchar>|<p_int>>
  |<#p_varchar:"varchar("<p_NUM>")">
  |<#p_int:"int("<p_NUM>")" >
  |<#p_NUM:(["0" - "9"])+>
}

String convertSQL():{
  Token t;
  String temp="";
  StringBuffer sb=new StringBuffer();
}
{ 
   ( 
   <CREATE>
   <FUNCTION>   
   t=<FUNCNAME>
   {
     sb.append(" create or replace function  " );
     sb.append(" "+t.image+" ");
   }
    t= <papams> 
    {
    sb.append(t.image.replace("@",""));
    }  
    t= <RETURN>  
    {
   	sb.append(" "+t.image+" ");
   }
    t=<VARCHAR> 
   {
   	sb.append(" "+t.image+" ");
   }
   )*
   {
     return sb.toString();
   }
}
 

 建立完文件后,javaCC会自动生成相关的类

如下:


 

打开eg1.java,执行即可;

OLDSQL:  --  CREATE   FUNC  test(@pdata varchar(20),@pint int(10))   RETURN  varchar(30) 
Call:   convertSQL
  Consumed token: <<CREATE>: " CREATE " at line 1 column 6>
  Consumed token: <<FUNCTION>: " FUNC " at line 1 column 15>
  Consumed token: <<FUNCNAME>: "test" at line 1 column 22>
  Consumed token: <<papams>: "(@pdata varchar(20),@pint int(10))" at line 1 column 26>
  Consumed token: <<RETURN>: " RETURN " at line 1 column 62>
  Consumed token: <<VARCHAR>: "varchar(30)" at line 1 column 71>
Return: convertSQL
SQL: create or replace function   test (pdata varchar(20),pint int(10))  RETURN   varchar(30) 

 可见已经正常识别了!

 

如需扩展,还需深入研究,看见官方例子,该软件还是很强大的
 

  • 大小: 7.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics