讨论一下 SQL 解析器

闭包客 2018-02-28 05:21:24
加精
相信很多人都使用过 SQL 语句拼接的帮助方法。使用的场景是动态 SQL 条件,SQL 分页等。

我一直觉得仅靠帮助方法是不够的,比如在使用了 union,子查询,和分布式数据库的情况下,帮助方法可能并不能满足需求。因此想写一个完整的 SQL 解析器,完整的解析器可以得到 SQL 语句的抽象语法树,也就是可以对 SQL 进行任何的结构化修改,而不需要拼接字符串。

我现在采用正则匹配的方法试了一下,测试用用例如下,暂时只写了 Count() 和 And() 方法:


//
string count = "select * from user where delete = 0 order by id desc limit {0}, {1}".Count();

Assert.IsTrue(count == "select count(*) from user where delete = 0");

count = "select * from user where delete = 0".Count();

Assert.IsTrue(count == "select count(*) from user where delete = 0");

count = "select * from user".Count();

Assert.IsTrue(count == "select count(*) from user");

count = "select id, name, dept from user where delete = 0 order by id desc limit {0}, {1}".Count();

Assert.IsTrue(count == "select count(*) from user where delete = 0");

count = "select id, name, dept from user where delete = 0".Count();

Assert.IsTrue(count == "select count(*) from user where delete = 0");

count = "select id, name, dept from user".Count();

Assert.IsTrue(count == "select count(*) from user");

//
string and = "select * from user where delete = 0 order by id desc limit {0}, {1}".And("status = 1");

Assert.IsTrue(and == "select * from user where delete = 0 and status = 1 order by id desc limit {0}, {1}");

and = "select * from user order by id desc limit {0}, {1}".And("status = 1");

Assert.IsTrue(and == "select * from user where status = 1 order by id desc limit {0}, {1}");

and =
@"select * from user
order by id desc
limit {0}, {1}".And("status = 1");

Assert.IsTrue(and ==
@"select * from user where status = 1
order by id desc
limit {0}, {1}");

and = "SELECT * FROM USER ORDER BY ID DESC LIMIT {0}, {1}".And("status = 1");

Assert.IsTrue(and.CompareIgnoreCase("select * from user where status = 1 order by id desc limit {0}, {1}"));


想在此收集一下意见。
...全文
5510 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
闭包客 2018-04-08
  • 打赏
  • 举报
回复
https://gitee.com/bibaoke/Less.SqlParser 源代码地址,正在编写中……
jacobwind 2018-03-26
  • 打赏
  • 举报
回复
解析器从来没用过,也不知道有没有用
江南小书生 2018-03-15
  • 打赏
  • 举报
回复
解析器从来没用过,也不知道有没有用
闭包客 2018-03-05
  • 打赏
  • 举报
回复
引用 30 楼 xomix 的回复:
[quote=引用 28 楼 closurer 的回复:] [quote=引用 27 楼 xomix 的回复:] [quote=引用 25 楼 closurer 的回复:] [quote=引用 18 楼 xomix 的回复:] [quote=引用 17 楼 From_TaiWan 的回复:] 回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
有优秀的工具不去使用是自己的损失,拿出来炫耀就属于有点……了 ORM很多我就不说了,我说点别的。我现在维护的项目在使用的是利用存储过程接收入参实现分页、排序、条件查询拼接等控制,也很好用。 这方面有时候你钻的太深入,就会变成想实现一个C#托管的T-Sql语句再生产模块了。[/quote] 我认为使用存储过程来实现分页、排序、条件查询拼接等,很难提高开发效率。SQL 拼接字符串的能力,比 C#、Java 等编程语言还要差不少。 [/quote] 确实要少很多,但是你要是想要提高开发效率,EF、Linq to Sql 这两对开发效率的提升不是一点半点。我猜你又要用这两个模块的运行效率来所不合适。 其实你只是想要别人做出来方便你使用的东西而已。[/quote] 我对 EF 的运行效率,或者说所有 ORM 的运行效率是没有意见的。我对 ORM 的意见在于表达有一定的复杂程度的 SQL的时候,比如多表连接,嵌套的子查询,所写的代码比 SQL 更多,更难写,也更难读。 [/quote] 我不会我没学我懒得学就是难我不管我不管我要我学过的东西变得更方便就是你了。[/quote] 建议你先了解一下 MyBatis 为什么会越来越流行吧…… 用存储过程来拼接分页语句,还要觉得好用,真不知道说你什么好。 东施觉得自己是美女也是有自信的表现,你加油吧!
  • 打赏
  • 举报
回复
引用 28 楼 closurer 的回复:
[quote=引用 27 楼 xomix 的回复:] [quote=引用 25 楼 closurer 的回复:] [quote=引用 18 楼 xomix 的回复:] [quote=引用 17 楼 From_TaiWan 的回复:] 回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
有优秀的工具不去使用是自己的损失,拿出来炫耀就属于有点……了 ORM很多我就不说了,我说点别的。我现在维护的项目在使用的是利用存储过程接收入参实现分页、排序、条件查询拼接等控制,也很好用。 这方面有时候你钻的太深入,就会变成想实现一个C#托管的T-Sql语句再生产模块了。[/quote] 我认为使用存储过程来实现分页、排序、条件查询拼接等,很难提高开发效率。SQL 拼接字符串的能力,比 C#、Java 等编程语言还要差不少。 [/quote] 确实要少很多,但是你要是想要提高开发效率,EF、Linq to Sql 这两对开发效率的提升不是一点半点。我猜你又要用这两个模块的运行效率来所不合适。 其实你只是想要别人做出来方便你使用的东西而已。[/quote] 我对 EF 的运行效率,或者说所有 ORM 的运行效率是没有意见的。我对 ORM 的意见在于表达有一定的复杂程度的 SQL的时候,比如多表连接,嵌套的子查询,所写的代码比 SQL 更多,更难写,也更难读。 [/quote] 我不会我没学我懒得学就是难我不管我不管我要我学过的东西变得更方便就是你了。
xuzuning 2018-03-02
  • 打赏
  • 举报
回复
那你自己改造一下呗
闭包客 2018-03-02
  • 打赏
  • 举报
回复
引用 27 楼 xomix 的回复:
[quote=引用 25 楼 closurer 的回复:] [quote=引用 18 楼 xomix 的回复:] [quote=引用 17 楼 From_TaiWan 的回复:] 回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
有优秀的工具不去使用是自己的损失,拿出来炫耀就属于有点……了 ORM很多我就不说了,我说点别的。我现在维护的项目在使用的是利用存储过程接收入参实现分页、排序、条件查询拼接等控制,也很好用。 这方面有时候你钻的太深入,就会变成想实现一个C#托管的T-Sql语句再生产模块了。[/quote] 我认为使用存储过程来实现分页、排序、条件查询拼接等,很难提高开发效率。SQL 拼接字符串的能力,比 C#、Java 等编程语言还要差不少。 [/quote] 确实要少很多,但是你要是想要提高开发效率,EF、Linq to Sql 这两对开发效率的提升不是一点半点。我猜你又要用这两个模块的运行效率来所不合适。 其实你只是想要别人做出来方便你使用的东西而已。[/quote] 我对 EF 的运行效率,或者说所有 ORM 的运行效率是没有意见的。我对 ORM 的意见在于表达有一定的复杂程度的 SQL的时候,比如多表连接,嵌套的子查询,所写的代码比 SQL 更多,更难写,也更难读。
  • 打赏
  • 举报
回复
引用 25 楼 closurer 的回复:
[quote=引用 18 楼 xomix 的回复:] [quote=引用 17 楼 From_TaiWan 的回复:] 回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
有优秀的工具不去使用是自己的损失,拿出来炫耀就属于有点……了 ORM很多我就不说了,我说点别的。我现在维护的项目在使用的是利用存储过程接收入参实现分页、排序、条件查询拼接等控制,也很好用。 这方面有时候你钻的太深入,就会变成想实现一个C#托管的T-Sql语句再生产模块了。[/quote] 我认为使用存储过程来实现分页、排序、条件查询拼接等,很难提高开发效率。SQL 拼接字符串的能力,比 C#、Java 等编程语言还要差不少。 [/quote] 确实要少很多,但是你要是想要提高开发效率,EF、Linq to Sql 这两对开发效率的提升不是一点半点。我猜你又要用这两个模块的运行效率来所不合适。 其实你只是想要别人做出来方便你使用的东西而已。
闭包客 2018-03-02
  • 打赏
  • 举报
回复
引用 21 楼 wanghui0380 的回复:
引用
不过我倾向于手写,原因有两个:一是 SQL 需要修改,一般的解析器都只支持解析,修改的部分还是要自己去写;二是 SQL 存在多种流行的标准,MySQL 的、MSSQL 的等等,格式有所不同。也就是说,用第三方的解析器,还是要有相当的部分要自己去实现。
其实我一楼已经说过了,无论是irony,还是antlr4 都是可以自己修改的。因为他们本来的设计目标就是“词法解析” 这样把,irony词法规则是自己定义的大概类似yacc的规则,这个网上不好找 我们来看 antlr4的词法规则定义,antlr4的规则基本是BNF定义,同时antlr4也是一个流传了很多年的词法解析工具,所以他的资料比较好找。 so,我们来看下面一个东西 https://github.com/antlr/grammars-v4 你可以看到,其实把别人已经把你要的东西都写完了,plsql,tsql,mssql,连sqllite都给你写了。当然这种东西实际上可以自己定义的,我甚至可以用他来翻译解释我现在写下的这一整段中文。(别奇怪,俺们讯飞童鞋,在1年前还在用BNF词法分析做,中文智能语义分析。不过现在讯飞也升级了,玩神经网络,机器学习去搞语义分析这块了)
修改别人的开源项目是比较难的,要谨慎考虑。 antlr4 对于我的需求来说,最有吸引力的是不需要再去了解 SQL 的完整语义,这是一个很繁琐的工作。
闭包客 2018-03-02
  • 打赏
  • 举报
回复
引用 18 楼 xomix 的回复:
[quote=引用 17 楼 From_TaiWan 的回复:] 回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
有优秀的工具不去使用是自己的损失,拿出来炫耀就属于有点……了 ORM很多我就不说了,我说点别的。我现在维护的项目在使用的是利用存储过程接收入参实现分页、排序、条件查询拼接等控制,也很好用。 这方面有时候你钻的太深入,就会变成想实现一个C#托管的T-Sql语句再生产模块了。[/quote] 我认为使用存储过程来实现分页、排序、条件查询拼接等,很难提高开发效率。SQL 拼接字符串的能力,比 C#、Java 等编程语言还要差不少。
闭包客 2018-03-02
  • 打赏
  • 举报
回复
谢谢大家的意见! 总的来说,我说要写解析器,会得到两种回复: 1、为什么不用 ORM? 2、这个跟 SqlHelper.cs 等帮助类有什么不同? ORM 和 SQL 的选择问题,本身就可以花很大的篇幅去讨论,这里就不具体说了。我个人倾向使用 SQL 语句要多于 ORM,我曾经谈过几句这个问题 :http://bibaoke.com/tweet#104 几年前 Hibernate 等 ORM 很流行,现在有所减退,Java 程序员更加喜欢使用 SQL 的 MyBatis,这种现象是很好的思考 ORM 与 SQL 的选择问题的切入点。 其实我想做的事情,和 SQL 帮助类更加接近,可以说是一个功能完全的 SQL 帮助类,一般的 SQL 帮助类,只能处理简单的分页,插入条件等。但是在嵌套的子查询中,插入一个子查询这种较为复杂的,是 SQL 帮助类做不到的。只有对 SQL 的完全解析之后才可以做到。
秋的红果实 2018-03-01
  • 打赏
  • 举报
回复
回来再补充一点,本人在实际项目中,从来不用什么EF、linq to sql之类的,尽管理论上知道些
秋的红果实 2018-03-01
  • 打赏
  • 举报
回复
我不会花时间去做这件事的 成熟的ORM产品已经很多了,sql有自己的数据库操纵语言,功能非常强大,在架构一个系统的时候,有时甚至会考虑将一个模块的功能扔给sql服务去做,别认为这是笑柄,sql服务运行了多年,经过多少次的升级改进,人家的可靠性、性能、安全等绝不比你自己设计的程序功能差 尽管这种设计思路有争议 研究sql具体指令才是正道,造万能钥匙的想法有待讨论 话说回来,我这只是自己的观点,鼓励lz的想法,支持一个!望早日实现
xuzuning 2018-03-01
  • 打赏
  • 举报
回复
既然是 【想设计一个结构,方便组织 SQL 指令的成分,以便于 SQL 指令的生成】 那么先假定用户根本就不懂 SQL,那么你要的就是一个 ORM 通过 ORM 提供的方法,用户就可方便的操作数据库,和操作普通对象一样。并不需要管最终是以命令方式还是参数化方式操作数据库的(因为用户可以根本不需要知道数据库是什么玩意) ORM 已经流行多年了,无论是你套用一个现成的还是自己全新开发一个,都不是什么很困难的事情
exception92 2018-03-01
  • 打赏
  • 举报
回复
太深奥了,只注重数据查询更新的效率,管它怎么去解析的。
正怒月神 2018-03-01
  • 打赏
  • 举报
回复
引用 12 楼 closurer 的回复:
[quote=引用 8 楼 hanjun0612 的回复:] 闭包客,我觉得你可以直接从 Expression入手啊。 linq中的 表达式树就是你想做的事情吧。
linq to sql 的表达式可以映射成 SQL 语句,我想做的事情和这个差不多。但是 linq to sql 只能生成,它不能解析一个 SQL 语句之后,再结构化地修改。 另外,我以前使用 linq to sql 的时候,还发现一个局限,就是它只能把一些基本的函数映射成 SQL 语句,比如 ==、Contains, 如果是一个自己写的函数,是不能生成 SQL 语句的。 [/quote] 的确如此,自己写的方法,在表达式中无效。 不过为何要在linq解析后,结构化修改呢。 如果需要修改的话。,应该在expression中修改树的节点吧。
闭包客 2018-03-01
  • 打赏
  • 举报
回复
引用 8 楼 hanjun0612 的回复:
闭包客,我觉得你可以直接从 Expression入手啊。 linq中的 表达式树就是你想做的事情吧。
linq to sql 的表达式可以映射成 SQL 语句,我想做的事情和这个差不多。但是 linq to sql 只能生成,它不能解析一个 SQL 语句之后,再结构化地修改。 另外,我以前使用 linq to sql 的时候,还发现一个局限,就是它只能把一些基本的函数映射成 SQL 语句,比如 ==、Contains, 如果是一个自己写的函数,是不能生成 SQL 语句的。
闭包客 2018-03-01
  • 打赏
  • 举报
回复
引用 6 楼 sp1234 的回复:
“倾向于手写”跟首先研究人家成熟的类库的源代码并不矛盾。 如果你谈论的是语义分析、语法分析系统的术语,而不是什么“拿正则匹配的方法试了一下”,这就说明你上道、在那一个真正有行动力圈子里。
手写是不必要研究别人的类库的,只需要知道 SQL 的定义就行了。 实际上,一定程度上使用正则,是写解析器的好方法。
闭包客 2018-03-01
  • 打赏
  • 举报
回复
引用 7 楼 xuzuning 的回复:
不知道你想要做什么事情 如果 SQL 指令已经存在了,自己写个语法分析器似乎并无此必要。毕竟 SQL 指令的语法简单,约束也大。能写出来,就不大会有语法错的 如果是想设计一个结构,方便组织 SQL 指令的成分,以便于 SQL 指令的生成。却又说 不需要拼接字符串(机器拼也是拼),不觉得自相矛盾吗 不借助第三方工具,解析简单语法的最佳方法是通过 Trie 树,生成树和查询的代码也就 二、三十行。 而且对正文只需做一遍扫描,而正则需要多趟扫描
我想做的是你说的【想设计一个结构,方便组织 SQL 指令的成分,以便于 SQL 指令的生成】 我所说的不要拼接,是不需要用 + 、Format、Concat 等基本方法。
诺丽果 2018-03-01
  • 打赏
  • 举报
回复
真没深层次的考虑过这些,平时也只是直接写sql啥的
加载更多回复(12)

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧