您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

c# 怎样能写个sql的解析器

时间:2022-09-01 15:10:44  来源:  作者:中年农码工

本示例主要是讲明sql解析的原理。

前言

阅读本文需要有一定正则表达式基础 正则表达式基础教程 ,和编译原理的基础。有使用过VUE的伙伴可能知道vue是自定了模版解析编译器的,vue用的是标准的AST语法树统计,如果对语法树不了了解的请查看 什么是AST抽像语法树

本示例介绍的是参考编译原理 词法分析->语法分析->构建AST语法树->解析成目标sql 的流程来实现

示例

sqlserver 的一条查询语句

select  a.UniqueCode,a.BarCode,a.CategoryId from GD_UniqueCodeInfo as a

假如我们要将以上代码进行格式化成以下方式

select  [a].[UniqueCode],[a].[BarCode],[a].[CategoryId] from [GD_UniqueCodeInfo] as [a]

分析

首先我们来分析一下这个语句有什么特点。

  1. 找关键词
    这个sql语法有三个关键词如select ,from,as
  2. 找结构
    有字段信息a.UniqueCode,a.BarCode,a.CategoryId,有表名信息GD_UniqueCodeInfo 还有 被重命名的表信息a 这些信息可能符合命名规范可能有些不符合,那么在解析时都要进行检测出来
  3. 标识符
    在生成的目标sql语句中有[] 这个的作用主要是万一字段名出现与关键词有相同的字段名称能进行正常识别

开始

首先我们先创建两个c#解析正则表达式的方法

这个方法就是可以将正则表达式中的匹配数据提出来返回一个字典数据

  public static Dictionary<string, string> RegexGrp(string regex,string text)
  {
        Regex _regex = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Multiline);
        Dictionary<string, string> _dic = new Dictionary<string, string>();
        Match _match = _regex.Match(text);
        while (_match.Success)
        {
            foreach (string name in _regex.GetGroupNames())
            {
                if(!_dic.ContAInsKey(name))
                    _dic.Add(name, _match.Groups[_regex.GroupNumberFromName(name)].Value);
            }
            _match = _match.NextMatch();
        }
        return _dic;
  }

检测正则表达工是否正确匹配

public static bool RegexMatch(string regex, string text)
        {
            Regex _regex = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            Match _match = _regex.Match(text);
            return _match.Success;
        }

第一步 先检测这个sql语句是否是一个查询语句

正则代码:^s*(?<cmd>select)s+(?<field>[wsS]+(?=bfromb))(?:bfromb)(?<from>(?:[s]+)(?<flag>[#]{1,2}|[@]{1})?(?<tab>[w]+)s*[swS]*)

那么我们来验证下
通过把要解析的SQL语句放入测试工具中运行

 

在右下方的区域通过正则匹配已经把该语句结构已经拆解出来了
cmd:select
field:a.UniqueCode,a.BarCode,a.CategoryId
tab:GD_UniqueCodeInfo

一下就把SQL语句结构化出来了,有匹配结果说明是一个正常的sql语句

第二步 通过代码获取结构信息

  string sql="select  a.UniqueCode,a.BarCode,a.CategoryId from GD_UniqueCodeInfo as a";
  Dictionary<string, string> dic =RegexGrp(@"^s*(?<cmd>select)s+(?<field>[wsS]+(?=bfromb))(?:bfromb)(?<from>(?:[s]+)(?<flag>[#]{1,2}|[@]{1})?(?<tab>[w]+)s*[swS]*)",sql);

  if(dic.ConstainsKey("cmd"))
  {
    // 说明匹配成功
    Console.Write(dic["cmd"]);
    
  }


拆解select 后要把select 替换为空剩余的sql 为a.UniqueCode,a.BarCode,a.CategoryId from GD_UniqueCodeInfo as a

第三步 拆解字段

正则表达式:^s*(?<field>[wsS]*?(?=bfromb))
两通过测试工具测试一下

 

那么可以通过代码获取出来

  string sql="a.UniqueCode,a.BarCode,a.CategoryId from GD_UniqueCodeInfo as a";
  Dictionary<string, string> dic =RegexGrp(@"^s*(?<field>[wsS]*?(?=bfromb))",sql);
  if (dic.ContainsKey("field"))
  {
    //说明匹配成功 
  }

字段是有多个的 还要单独拆解成一个一个的字段,拆解字段的这个就不详细描述了,可以继续用正则表达式也可以用Split(',') 进行分拆

var _field=dic["field"];
var fields=_field.Split(',')

拆解完字段后 剩余的sql:from GD_UniqueCodeInfo as a

拆解from

正则表达式:^s*(?:bfromb)(?<from>(?:[s]+)(?<table>(?:[s]*)(?<flag>[#]{1,2}|[@]{1})?(?<tab>[w]+))s*(?:basbs*(?<asname>[w]+))?s*)
通过该正则表达式可以拆解出 通过 as 重命名的表
下面通过正则表达式工具测试一下

 

那么通过以下代码来获取

string sql="from GD_UniqueCodeInfo as a";
  Dictionary<string, string> dic =RegexGrp(@"^s*(?:bfromb)(?<from>(?:[s]+)(?<table>(?:[s]*)(?<flag>[#]{1,2}|[@]{1})?(?<tab>[w]+))s*(?:basbs*(?<asname>[w]+))?s*)",sql);
  if (dic.ContainsKey("tab"))
  {
    //说明匹配成功 
  }

此时 就通过正则表达式拆解完成,但还需要对它进行结构化



Tags:c#   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C# 中15个值得收藏的开源项目推荐
在开源的世界里,C# 编程语言也占有一席之地。这些开源项目涵盖了多个领域,从框架、库到工具,它们为C#开发者提供了丰富的资源和工具,帮助他们更高效地开发、测试和部署应用程序...【详细内容】
2024-03-20  Search: c#  点击:(30)  评论:(0)  加入收藏
C# 线程本地存储为什么线程间值不一样
为什么用 ThreadStatic 标记的字段,只有第一个线程拿到了初始值,其他线程都是默认值,让我能不能帮他解答一下,尼玛,我也不是神仙什么都懂,既然问了,那我试着帮他解答一下,也给后面类...【详细内容】
2024-01-26  Search: c#  点击:(70)  评论:(0)  加入收藏
C# 登顶!超越Java或非空想
整理丨诺亚出品 | 51CTO技术栈(微信号:blog51cto)近日,TIOBE编程社区公布年度编程语言,此次摘得这一桂冠的是C#。这也是C#在TIOBE二十多年评选历史中首次赢得这一年度大奖。C#虽...【详细内容】
2024-01-15  Search: c#  点击:(117)  评论:(0)  加入收藏
如何通过 C# 比较两幅图片的相似度?
咨询区 Byyo我在用 C# 实现一个可以查找重复图片的小工具,我目前是给每一个图片做一个 md5 码,然后通过 md5 值来判断图片是否相同。但现实情况要复杂的多,比如: 图片被旋转...【详细内容】
2023-09-28  Search: c#  点击:(282)  评论:(0)  加入收藏
C# 如何判断某个 TCP 端口是否被占用?
在C#中使用TcpClient或者其他通用的方式建立的Socket,该如何判断这个端口是否被占用?比如下面的代码:TcpClient tc = new TcpClient(ip,port);在C#中,可以使用 System.Net.Netwo...【详细内容】
2023-09-26  Search: c#  点击:(54)  评论:(0)  加入收藏
适合每位开发人员的 60 个 C# 代码片段
嘿! 今天,我有一些特别的东西要与大家分享 - 60 个 C# 代码片段的汇编,我发现它们对我自己的工作非常有帮助。在本文中,我们不仅要了解这些片段如何解决日常编程问题,还要了解它...【详细内容】
2023-09-01  Search: c#  点击:(331)  评论:(0)  加入收藏
C# 语法糖之聊聊 Span 的底层玩法
把 Span 归于语法糖,可能有些偏了,但偏了就偏了,哈哈,只要是分享就好,C# 发展至今,已经是一门非常重的语言了,所有想要的它都要,即可以: 面向过程编程 面向对象编程 面向函数式编程 ...【详细内容】
2023-09-01  Search: c#  点击:(288)  评论:(0)  加入收藏
C# partial关键字
1.概要聊到partial关键字大家可能会有点陌生,在经常写WPF的开发者中一定见过但是没有主动去使用过这个关键字。那么这里我们就来看看这个关键字除了在WPF的window里使用还有...【详细内容】
2023-08-30  Search: c#  点击:(353)  评论:(0)  加入收藏
C# AsyncLocal如何在异步间进行数据流转
前言在异步编程中,处理异步操作之间的数据流转是一个比较常用的操作。C#异步编程提供了一个强大的工具来解决这个问题,那就是AsyncLocal。它是一个线程本地存储的机制,可以在异...【详细内容】
2023-08-29  Search: c#  点击:(459)  评论:(0)  加入收藏
C# 中的 ref 已经被放开,或许你已经不认识了
一:背景1. 讲故事最近在翻 netcore 源码看,发现框架中有不少的代码都被 ref 给修饰了,我去,这还是我认识的 ref 吗?就拿 Span 来说,代码如下:public readonly ref struct Span<T>...【详细内容】
2023-08-28  Search: c#  点击:(386)  评论:(0)  加入收藏
▌简易百科推荐
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  鲨鱼编程  微信公众号  Tags:C++   点击:(2)  评论:(0)  加入收藏
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  腾讯技术工程    Tags:C++   点击:(6)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25    CSDN  Tags:C++   点击:(5)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  AI让生活更美好  微信公众号  Tags:C++   点击:(24)  评论:(0)  加入收藏
C# 中15个值得收藏的开源项目推荐
在开源的世界里,C# 编程语言也占有一席之地。这些开源项目涵盖了多个领域,从框架、库到工具,它们为C#开发者提供了丰富的资源和工具,帮助他们更高效地开发、测试和部署应用程序...【详细内容】
2024-03-20  程序员编程日记  微信公众号  Tags:C#   点击:(30)  评论:(0)  加入收藏
C#异步编程:Task.Run vs. async-await,掌握基础与高级用法
概述:C#中的异步编程有两主要方式:Task.Run用于在后台线程执行同步操作,而async-await更适用于清晰表达异步流程。基础用法展示了它们的简单应用,高级用法则演示了它们的结合使...【详细内容】
2024-03-09  架构师老卢  今日头条  Tags:C#   点击:(26)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03     AI让生活更美好  Tags:C++   点击:(70)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  AI让生活更美好  微信公众号  Tags:C++   点击:(117)  评论:(0)  加入收藏
C# 线程本地存储为什么线程间值不一样
为什么用 ThreadStatic 标记的字段,只有第一个线程拿到了初始值,其他线程都是默认值,让我能不能帮他解答一下,尼玛,我也不是神仙什么都懂,既然问了,那我试着帮他解答一下,也给后面类...【详细内容】
2024-01-26  一线码农聊技术  微信公众号  Tags:C#   点击:(70)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  鲨鱼编程  微信公众号  Tags:C++   点击:(116)  评论:(0)  加入收藏
站内最新
站内热门
站内头条