JSQLParser是github上一个开源的项目,专门解析SQL,可以轻松地得到一条SQL的列、表、条件等对象,

JSQLParser碰到的问题_数据库

P.S. https://github.com/JSQLParser/JSqlParser

最近在做一个功能开发的时候,被他困扰了下,从需求来讲,就是利用正则,先将多行的SQL改成一行,然后通过JSQLParser解析SQL,但是在这过程中,碰到了很多问题。

问题1,提示EOF

最崩溃的,就是这个错误,

Encountered unexpected token: EOF

EOF我们在C中经常看到的,表示文件结尾,End Of File,但在这提示,一开始确实迷惑,忽略中间各种盲测调试,其实问题就出在所有的SQL合并到单行,如果存在"--"这种语法就会导致"--"跟着的所有内容,都是注释,如果之前的内容恰巧不能构成一条正确的SQL,就会提示未找到正确的结尾。

场景1,字段中出现"--内容",

select c1, --测试字段
       c2, c3
  from test1
  join test2
 where test1.id = test2.id;

场景2,字段中出现"--无内容",

select c1, --
       c2, c3
  from test1
  join test2
 where test1.id = test2.id;

场景3,WHERE条件中出现"--内容",

select c1, --测试字段
       c2, c3
  from test1
  join test2
 where test1.id = test2.id --连接
   and test1.id = 1;

以上三个场景,如果要将SQL整合成为一行,就需要替换这些"--",

replaceAll("--.+[^.+]", " ")
.replaceAll("--[^.+]", " ")
.replaceAll("[\r\n]", " ");

问题2,提示"\\"

Encountered: "\\" after : ""

通过SQL,

select c1, --测试字段
       c2,
       REPLACE(REPLACE(to_char(SUBSTR(regexp_REPLACE(c3, '\s',''),1,25)),'\','\\'),'"','\"') AS c3
  from test1
  join test2
 where test1.id = test2.id;

定位到是REPLACE函数中用到的"\\",

regexp_REPLACE(TEST, '\s',''),1,25)),'\','\\')

因此再增加对"\\"的函数替换,将其改为统一的"XXX",

.replaceAll("\\\\", "XXX")

问题3,提示\uff01

Encountered: "\uff01" (65281), after : ""

\uff01这个其实是中文的叹号,

>>> print(u'\uff01')
!(中文叹号)

除了这种中文叹号的使用,还出现了中文的括号,"("和")",如下所示,

场景1 中文叹号,

select c1, --测试字段
       c2, c3
  from test1
  join test2
 where test1.id = test2.id and test1.output !(此处是中文叹号)= 1;

场景2,中文括号,

select c1, --测试字段
       c2, c3
  from test1
  join test2
 where test1.id = test2.id 
   and test1.output in ((此处是中文括号)1, 2, 3)(此处是中文括号);

我们知道,SQL中使用中文符号,执行报错,如下所示,

SQL> select * from test where owner !='a';
select * from test where owner !='a'
                               *
ERROR at line 1:
ORA-00911: invalid character

但是既然出现了,程序上就得规避,hard code对这些字符,进行替换,

.replaceAll("!", "!")      // 替换中文的!
.replaceAll("(", "(")      // 替换中文的(
.replaceAll(")", ")");     // 替换中文的)

从这个处理过程我们能看到,SQL的标准写法上,其实还是有很多值得遵循的,所谓无规矩,不成方圆,还是有他的道理。