ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2022-06-30 11:31:17  阅读:194  来源: 互联网

标签:解析器 regex c# dic GD sql UniqueCodeInfo select


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

本示例主要是讲明sql解析的原理,真实的源代码下查看 sql解析器源代码
详细示例DEMO 请查看demo代码

前言

阅读本文需要有一定正则表达式基础 正则表达式基础教程 ,和编译原理的基础。有使用过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>[\w\s\S]+(?=\bfrom\b))(?:\bfrom\b)(?<from>(?:[\s]+)(?<flag>[\#]{1,2}|[\@]{1})?(?<tab>[\w]+)\s*[\s\w\S]*)

那么我们来验证下
通过把要解析的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>[\w\s\S]+(?=\bfrom\b))(?:\bfrom\b)(?<from>(?:[\s]+)(?<flag>[\#]{1,2}|[\@]{1})?(?<tab>[\w]+)\s*[\s\w\S]*)",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>[\w\s\S]*?(?=\bfrom\b))
两通过测试工具测试一下

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

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

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

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

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

拆解from

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

那么通过以下代码来获取

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

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

以下是代码截图片段

请查看demo代码

语法参考 hisql语法

标签:解析器,regex,c#,dic,GD,sql,UniqueCodeInfo,select
来源: https://www.cnblogs.com/tansar/p/16426224.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有