? ? ? ? ?前段时间,研究数据库迁移工作,使用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: convertSQLSQL: create or replace function test (pdata varchar(20),pint int(10)) RETURN varchar(30)
?可见已经正常识别了!
?
如需扩展,还需深入研究,看见官方例子,该软件还是很强大的
?