C#如何不区分大小写解析拆分SQL字符串的各组成部分
问题解决实现方案
你当前用String.Split的实现有两个明显缺陷:一是默认大小写敏感,无法匹配不同大小写形式的SQL关键字;二是硬编码单词分隔符的方式无法支持group by、order by这类多词关键字,还可能把字段值、表名字段名里包含的关键字误识别为拆分点。
推荐实现:基于正则匹配子句位置切片
这个方案可以同时解决大小写不敏感、多关键字支持、避免误匹配的问题,实现逻辑是先识别所有子句关键字在SQL中的位置,再按位置切片提取对应子句内容,不需要手动拼接丢失的关键字。
首先引入需要的命名空间:
using System; using System.Collections.Generic; using System.Text.RegularExpressions;
提取方法代码:
public static Dictionary<string, string> ExtractSqlClauses(string sql) { // 关键字按长度从长到短排列,优先匹配长关键字,避免短关键字提前截断长匹配(比如优先匹配group by而非单独的group) var sqlKeywords = new[] { "select", "from", "where", "group by", "having", "order by", "left join", "right join", "inner join", "join", "limit", "offset" }; // 正则加单词边界\b,避免把表名、字段名、字段值里的关键字片段误识别为子句开头,比如表名from_user不会被误判为from子句 var matchPattern = $@"\b({string.Join("|", sqlKeywords)})\b"; var matches = Regex.Matches( sql, matchPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline ); var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (matches.Count == 0) return result; for (int i = 0; i < matches.Count; i++) { var current = matches[i]; int clauseStart = current.Index; int clauseEnd = i == matches.Count - 1 ? sql.Length : matches[i + 1].Index; // 提取子句内容并去除首尾多余空白 var clauseContent = sql.Substring(clauseStart, clauseEnd - clauseStart).Trim(); // key统一转小写,取值时不区分大小写 result[current.Value.ToLower()] = clauseContent; } return result; }
调用示例
var testSql = @"select Id, Name from Order where Id ='8675' and Name ='Test' group by Id, Name order by Id desc"; var clauses = ExtractSqlClauses(testSql); // 取值不区分key大小写,不管SQL里写的是from/From/FROM都能正常取到 var selectPart = clauses["select"]; // 返回:select Id, Name var fromPart = clauses["from"]; // 返回:from Order var wherePart = clauses["where"]; // 返回:where Id ='8675' and Name ='Test' var groupPart = clauses["group by"];// 返回:group by Id, Name var orderPart = clauses["order by"];// 返回:order by Id desc
不推荐的简化方案(仅适配简单场景)
如果你用的是.NET Core 2.1+/.NET 5+版本,String.Split本身支持传入大小写比较规则,但是这个方案无法处理多词关键字,也无法避免字段值中包含关键字导致的误拆分,仅适合非常简单的固定SQL场景:
var str = @"select Id, Name from Order where Id ='8675' and Name ='Test'"; String[] separators = { "from", "where" }; // 传入StringComparison.OrdinalIgnoreCase实现忽略大小写拆分 String[] strlist = str.Split(separators, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries, StringComparison.OrdinalIgnoreCase);
注意:如果需要处理包含子查询、嵌套语句、SQL注释的复杂SQL,不建议用字符串匹配的方式提取子句,应该使用专门的SQL语法解析库处理,避免匹配错误。
内容的提问来源于stack exchange,提问作者Renee
相关产品推荐
相关产品推荐

