irpas技术客

Java解析SQL的基本思路_剽悍一小兔_java sql解析

大大的周 1500

前些天发现了一个巨牛的人工智能学习博客,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转

天天在写sql,一直很好奇sql到底咋解析的,于是随便整个小demo。

比如sql是:

String sql = "select?name,score,sex?from?users?where?name = 'jack'?and?isdelete <> 1 ; ";

中间可能有1个或者多个空格,就想着怎么着也得有个分词的类,就叫做Tokenizer吧。

public class Tokenizer implements Iterator<String> { String[] tokens; int index = 0; public Tokenizer(String sql) throws BadSqlGrammarException { sql = sql.trim(); if (!sql.endsWith(";")) { throw new BadSqlGrammarException("SQL未正确结束!"); } //去除多余的空格 sql = sql.replace(";", " ;").replaceAll("\\s+", " "); //分词 tokens = sql.split(" "); } @Override public boolean hasNext() { return index < tokens.length; } @Override public String next() { return tokens[index++]; } }

实现Iterator是因为需要去遍历维护的String数组,方便后面解析。

然后是parser类,里面聚合一个Tokenizer的引用。

public class Parser { Tokenizer tokenizer; DBCmd cmd; Map<String, DBCmd> cmdMap = new HashMap<>(); public Parser(String sql) throws BadSqlGrammarException { //用查表法,代替一大堆的if else this.cmdMap.put("select", new SelectCmd()); this.tokenizer = new Tokenizer(sql); //根据第一个sql关键字来确定是什么sql命令 this.cmd = this.cmdMap.get(tokenizer.next()); if (cmd == null) throw new BadSqlGrammarException("未识别的sql命令!"); } public void query() throws BadSqlGrammarException { cmd.query(tokenizer); } }

DBCmd做成一个抽象类,不同的命令需要单独设计一个类,去继承他。DBCmd就弄一些通用的方法即可。

public abstract class DBCmd { public abstract void query(Tokenizer tokenizer) throws BadSqlGrammarException; protected String splitUntilEnd(Tokenizer tokenizer) throws BadSqlGrammarException { return splitUntil(tokenizer, ";"); } protected String splitUntil(Tokenizer tokenizer, String until) throws BadSqlGrammarException { StringBuffer sb = new StringBuffer(); boolean find = false; while (tokenizer.hasNext()) { String next = tokenizer.next(); if (!next.equals(until)) { sb.append(next).append(" "); continue; } else { find = true; break; } } if (!find) throw new BadSqlGrammarException("语法不正确"); return sb.toString(); } }

只测试一下select语法,所以只写一个select操作类。

public class SelectCmd extends DBCmd { @Override public void query(Tokenizer tokenizer) throws BadSqlGrammarException { String querys = splitUntil(tokenizer, "from"); String tableName = tokenizer.next(); String condition = null; if (tokenizer.hasNext() && tokenizer.next().equals("where")) { condition = splitUntilEnd(tokenizer); } System.out.println("查询字段:" + querys); System.out.println("查询表:" + tableName); System.out.println("查询条件:" + condition); } }

最后测试一下子:

public static void main(String[]args)throws BadSqlGrammarException{ String sql="select name,score,sex from users where name = 'jack' and isdelete <> 1 ; "; Parser parser=new Parser(sql); parser.query(); }

效果:

查询字段:name,score,sex查询表:users查询条件:name = 'jack' and isdelete <> 1

仔细一想,如果涉及到连表,where条件多层嵌套,甚至子查询,就GG了。实在是够复杂的。本文仅为抛砖引玉,匿了。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #JAVA #sql解析 #比如sql是String #SQL #quotselectname #score